Учитывая следующую таблицу

Значение последовательности - это пользовательский ключ автоинкремента, объединяющий буквы и цифры, которые нужны конкретному клиенту для его системы.
Мы создали функцию GetNextSequence (), которая должна возвращать следующее значение последовательности. Шаг для чтения и обновления последовательности идет следующим образом
- Считать значение последовательности, используя KeyId:
SELECT Sequence FROM [Key] WHERE KeyId = @Id
- Разобрать значение последовательности и определить следующее значение
- Запишите значение последовательности в таблицу:
UPDATE [Key] SET Sequence = @Sequence WHERE KeyId = @Id
Вот код C # (упрощенный для ясности):
var transaction = connection.BeginTransaction(IsolationLevel.RepeatableRead);
var currentSequenceValue = SqlUtils.ExecuteScalar(connection, transaction, "SELECT Sequence FROM [Key] WHERE KeyId = @Id", new SqlParameter("@Id", keyId));
var updatedSequenceValue = ParseSequence(currentSequenceValue);
SqlUtils.ExecuteScalar(connection, transaction, "UPDATE [Key] SET Sequence = @Sequence WHERE KeyId = @Id", new SqlParameter("@Id", keyId), new SqlParameter("@Sequence", updatedSequenceValue));
transaction.Commit();
return updatedSequenceValue;
Наша проблема заключается в том, что два разных сервера могут обращаться к одной и той же последовательности, и мы в итоге заходим в тупик
Транзакция (идентификатор процесса X) заблокирована для ресурсов блокировки с другим процессом и выбрана в качестве жертвы тупика. Перезапустите транзакцию.
В C # я пытался установить другую комбинацию блокировок, например изоляцию транзакции IsolationLevel.RepeatableRead
или IsolationLevel.Serializable
, или в SQL, используя табличные подсказки ROWLOCK
и HOLDLOCK
, но безуспешно.
Я хочу, чтобы каждый сервер мог читать, манипулировать и обновлять последовательность атомарным способом. Как правильно настроить блокировку для этой ситуации?