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,
|
||||
lockRow *serverLock, dbSession *sqlstore.DBSession) (*serverLock, error) {
|
||||
lockRow *serverLock, dbSession *sqlstore.DBSession,
|
||||
) (*serverLock, error) {
|
||||
affected := int64(1)
|
||||
rawSQL := `INSERT INTO server_lock (operation_uid, last_execution, version) VALUES (?, ?, ?)`
|
||||
if sl.SQLStore.GetDBType() == migrator.Postgres {
|
||||
rawSQL += ` RETURNING id`
|
||||
rawSQL += ` ON CONFLICT DO NOTHING RETURNING id`
|
||||
var id int64
|
||||
_, err := dbSession.SQL(rawSQL, lockRow.OperationUID, lockRow.LastExecution, 0).Get(&id)
|
||||
if err != nil {
|
||||
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
|
||||
} else {
|
||||
res, err := dbSession.Exec(
|
||||
|
Loading…
Reference in New Issue
Block a user