У меня есть хранимая процедура, которая вставляет запись в таблицу с порядковым номером токена. У меня есть другие хранимые процедуры, которые также будут вставлять записи в одну и ту же таблицу.
Я буду выполнять эти хранимые процедуры от разных пользователей веб-приложения.
В качестве примера у меня есть страница в моем веб-приложении с именем AddUser, к которой могут получить доступ OfficerA и OfficerB. Оба эти офицера могут одновременно нажать кнопку добавления, которая одновременно выполнит мою хранимую процедуру. В этом случае 2 новых пользователя получат одинаковый номер токена, чего не должно быть.
Я хочу создать механизм блокировки, когда, если один сотрудник выполняет процедуру, выполнение других сотрудников должно ЖДАТЬ, пока не завершится первый.
Я попробовал следующее. но не уверен, что этого достаточно для процесса WAIT
create procedure TokenInsertProc(<params here>)
as
begin
DECLARE @returnCode INT
BEGIN TRANSACTION;
BEGIN TRY
EXEC @returnCode = sp_getapplock
@Resource = 'TokenInsertProc',
@LockMode = 'Exclusive',
@LockOwner = 'Transaction',
@LockTimeout = 50,
@DbPrincipal = 'public'
IF @returnCode NOT IN (0, 1)
BEGIN
RAISERROR ( 'Unable to acquire exclusive Lock on TokenInsertProc', 16, 1 )
RETURN
END
-- my procedure insert script goes here
EXEC @returnCode = sp_releaseapplock
@Resource = 'TokenInsertProc',
@LockOwner = 'Transaction',
@DbPrincipal = 'public'
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @returnCode IN (0, 1)
BEGIN
EXEC @returnCode = sp_releaseapplock
@Resource = 'TokenInsertProc',
@LockOwner = 'Transaction',
@DbPrincipal = 'public'
END
DECLARE @ErrMsg VARCHAR(4000)
SELECT @ErrMsg = ERROR_MESSAGE()
RAISERROR(@ErrMsg, 15, 50)
ROLLBACK TRANSACTION;
END CATCH;
end
или просто
set transaction isolation level serializable
поможет?
create procedure TokenInsertProc(<params here>)
as
begin
DECLARE @returnCode INT
set transaction isolation level serializable
BEGIN TRANSACTION;
BEGIN TRY
-- my procedure insert script goes here
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH;
end
Любая помощь будет высоко ценится.
Редактировать 1
Для более подробного объяснения позвольте мне опубликовать структуру таблицы
TQHId TokenNo TokenStatus TokenSequence
1 A1 Pending 1
6 A2 Pending 2
7 B1 Pending 1
9 I3 Hold 3
10 I4 Pending 4
Здесь, в этой таблице
[TQHId] [int] IDENTITY(1,1) NOT NULL, CONSTRAINT [PK_TokenQHeader] PRIMARY KEY CLUSTERED
(
[TokenQHeaderId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
- поле идентификаторакоторый не имеет никакого отношения к токенно. Я использую это как поле первичного ключа. Мои номера токенов генерируются с использованием пользовательского кода внутри TokenInsertProc процедуры.
Как я уже упоминал, моя проблема заключается в том, что эту хранимую процедуру могут вызывать два разных веб-пользователя одновременно. Я хочу не получать одинаковый номер токена (только при выполнении процедуры) двум разным пользователям.