Как настроить блокировку внутри магазина? - PullRequest
1 голос
/ 10 февраля 2020

Я пытаюсь настроить блокировку чтения / записи на SQL сервере. Моя хранимая процедура -

CREATE PROCEDURE test()
AS
BEGIN
SELECT VALUE FROM MYTABLE WHERE ID=1
UPDATE MYTABLE SET VALUE=VALUE+1 WHERE ID=1
END

Я хотел бы быть уверен, что никто другой не будет читать или обновлять поле «Значение» во время выполнения этой хранимой процедуры. Я читаю много постов и читаю, что в SQL сервера должно быть достаточно для настройки транзакции.

CREATE PROCEDURE test()
AS
BEGIN
    BEGIN TRANSACTION
    SELECT VALUE FROM MYTABLE WHERE ID=1
    UPDATE MYTABLE SET VALUE=VALUE+1 WHERE ID=1
    COMMIT TRANSACTION
END

Но мне этого недостаточно, поскольку я попытался запустить два параллельных соединения, оба из они используют эту хранимую процедуру. С отладчиком SQL Server Management Studio я остановил первое выполнение внутри транзакции и заметил, что вторая транзакция была выполнена! Поэтому я попытался добавить УРОВЕНЬ ИЗОЛЯЦИИ

CREATE PROCEDURE test()
AS
BEGIN
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    BEGIN TRANSACTION
    SELECT VALUE FROM MYTABLE WHERE ID=1
UPDATE MYTABLE SET VALUE=VALUE+1 WHERE ID=1
    COMMIT TRANSACTION
END

, но результат тот же. Я также пытался установить уровень изоляции в клиентском коде

    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    EXEC test

, но опять ничего не изменилось.

Мой вопрос: в такой ситуации, как правильно установить блокировку, которая блокирует других? спасибо

1 Ответ

0 голосов
/ 10 февраля 2020

в такой ситуации, какой правильный способ установить блокировку, которая блокирует другие?

Правильная блокировка здесь - чтение таблицы с помощью UPDLOCK в транзакции .

SELECT VALUE FROM MYTABLE with (UPDLOCK)
WHERE ID=1

Вы также можете использовать предложение OUTPUT для обновления и возврата значения в одном запросе, что также не позволит двум сеансам читать и обновлять одно и то же значение

update MyTable set value = value+1
output inserted.value 

Однако вы должны , а не генерировать ключи, как это. Только один сеанс может генерировать ключ за раз, и блокировка для генерации ключа удерживается до конца текущей транзакции сеанса. Вместо этого используйте SEQUENCE или столбец IDENTITY.

...