mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ServerLock: Fix pg concurrency/locking issue (#95916)
Fix pg unique constraint validation in serverlock
This commit is contained in:
parent
7f560c13e4
commit
ab974ddf14
@ -352,16 +352,26 @@ func (sl *ServerLockService) executeFunc(ctx context.Context, actionName string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sl *ServerLockService) createLock(ctx context.Context,
|
func (sl *ServerLockService) createLock(ctx context.Context,
|
||||||
lockRow *serverLock, dbSession *sqlstore.DBSession) (*serverLock, error) {
|
lockRow *serverLock, dbSession *sqlstore.DBSession,
|
||||||
|
) (*serverLock, error) {
|
||||||
affected := int64(1)
|
affected := int64(1)
|
||||||
rawSQL := `INSERT INTO server_lock (operation_uid, last_execution, version) VALUES (?, ?, ?)`
|
rawSQL := `INSERT INTO server_lock (operation_uid, last_execution, version) VALUES (?, ?, ?)`
|
||||||
if sl.SQLStore.GetDBType() == migrator.Postgres {
|
if sl.SQLStore.GetDBType() == migrator.Postgres {
|
||||||
rawSQL += ` RETURNING id`
|
rawSQL += ` ON CONFLICT DO NOTHING RETURNING id`
|
||||||
var id int64
|
var id int64
|
||||||
_, err := dbSession.SQL(rawSQL, lockRow.OperationUID, lockRow.LastExecution, 0).Get(&id)
|
_, err := dbSession.SQL(rawSQL, lockRow.OperationUID, lockRow.LastExecution, 0).Get(&id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if id == 0 {
|
||||||
|
// Considering the default isolation level (READ COMMITTED), an entry could be added to the table
|
||||||
|
// between the SELECT and the INSERT. And inserting a row with the same operation_uid would violate the unique
|
||||||
|
// constraint. In this case, the ON CONFLICT DO NOTHING clause will prevent generating an error.
|
||||||
|
// And the returning id will be 0 which means that there wasn't any row inserted (another server has the lock),
|
||||||
|
// therefore we return the ServerLockExistsError.
|
||||||
|
// https://www.postgresql.org/docs/current/transaction-iso.html#XACT-READ-COMMITTED
|
||||||
|
return nil, &ServerLockExistsError{actionName: lockRow.OperationUID}
|
||||||
|
}
|
||||||
lockRow.Id = id
|
lockRow.Id = id
|
||||||
} else {
|
} else {
|
||||||
res, err := dbSession.Exec(
|
res, err := dbSession.Exec(
|
||||||
|
Loading…
Reference in New Issue
Block a user