У меня есть приложение, которое использует номера инцидентов (среди других типов номеров). Эти числа хранятся в таблице с именем Number_Setup, которая содержит текущее значение счетчика.
Когда приложение генерирует новый инцидент, оно отправляет таблицу number_setup и получает требуемую строку счетчика чисел (счетчики могут быть сброшены ежедневно, еженедельно и т. Д. И сохраняются как целые числа). Затем он увеличивает счетчик и обновляет строку новым значением.
Приложение является многопользовательским (приблизительно 100 пользователей одновременно, а также задания sql, которые запускают и получают 100 записей об инцидентах и запрашивают номера инцидентов для каждого). В таблице инцидентов есть несколько повторяющихся номеров инцидентов, где они не должны повторяться.
Сохраненный процесс используется для получения следующего счетчика.
SELECT @Counter = counter, @ShareId=share_id, @Id=id
FROM Number_Setup
WHERE LinkTo_ID=@LinkToId
AND Counter_Type='I'
IF isnull(@ShareId,0) > 0
BEGIN
-- use parent counter
SELECT @Counter = counter, @ID=id
FROM Number_Setup
WHERE Id=@ShareID
END
SELECT @NewCounter = @Counter + 1
UPDATE Number_Setup SET Counter = @NewCounter
WHERE id=@Id
Я сейчас окружил этот блок транзакцией, но я не совсем уверен, что он "на 100% решит проблему", так как я думаю, что все еще есть общие блокировки, поэтому счетчик может быть прочитан в любом случае.
Возможно, я смогу проверить, что счетчик не был обновлен, в операторе обновления
UPDATE Number_Setup SET Counter = @NewCounter
WHERE Counter = @Counter
IF @@ERROR = 0 AND @@ROWCOUNT > 0
COMMIT TRANSACTION
ELSE
ROLLBACK TRANSACTION
Я уверен, что это обычная проблема с номерами счетов в финансовых приложениях и т. Д.
Я также не могу поместить логику в код и использовать блокировку на этом уровне.
Я также заблокировал в HOLDLOCK, но я не уверен в его применении. Должен ли он быть помещен в два оператора SELECT?
Как я могу убедиться, что дубликаты не созданы?