SQL Server: как получить эксклюзивную блокировку, чтобы предотвратить состояние гонки? - PullRequest
3 голосов
/ 17 марта 2011

У меня есть следующий код T-SQL:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION T1_Test

    /*This is a dummy table used for "locking" 
    and it doesn't contain any meaningful data.*/        
    UPDATE lockTable 
        SET ID = 1    
        WHERE ID = 1

    DECLARE @Count TINYINT 

    SELECT @Count = COUNT(*)
    FROM debugSP 

    WAITFOR DELAY '00:00:5';

    INSERT INTO debugSP 
        (DateCreated, ClientId, Result)
    SELECT 
        GETDATE(), @@SPID, @Count

COMMIT TRANSACTION T1_Test

Я использую взлом "блокировки", помеченный комментарием, для получения эксклюзивной блокировки.

ПРИМЕЧАНИЕ: используя подсказки TABLOCKX или UPDLOCKне будет работать, потому что я нарушил ATOMIC-ity, разделив операторы и добавив команду WAITFOR в середине для целей тестирования.Я не хочу что-то подобное:

INSERT INTO debugSP (DateCreated, ClientId, Result)
SELECT GETDATE(), @@SPID, COUNT(*) 
FROM debugSP

Это правильный результат после запуска двух одновременных сеансов (с таблицей блокировок)

Id DateCreated           ClientId Result
-- ----------------------- -------- ------
 1 2011-03-17 15:52:12.287       66      0
 2 2011-03-17 15:52:24.534       68      1

, и это неверный результат выполнениязакомментированный код с блокировкой

Id DateCreated           ClientId Result
-- ----------------------- -------- ------
 1 2011-03-17 15:52:43.128       66      0
 2 2011-03-17 15:52:46.341       68      0

Есть ли лучший способ получить исключительную блокировку для транзакций без таких хаков?

Ответы [ 2 ]

7 голосов
/ 17 марта 2011

Я не совсем уверен, что вы пытаетесь сделать из размещенного кода.Я полагаю, вы просто пытаетесь сериализовать доступ к этому коду?В этом случае sp_getapplock должен делать то, что вам нужно, вместо создания новой фиктивной таблицы, которую вы просто используете для блокировки.

Подробности здесь

1 голос
/ 17 марта 2011

Можно использовать подсказку блокировки WITH (XLOCK, ROWLOCK) в рамках транзакции с изоляцией Repeatable Read. При Serializable изоляции эксклюзивная блокировка получается по умолчанию для операции чтения, поэтому, если вам нужно, чтобы конкретная транзакция воспроизводилась приятно параллельно, вы можете указать повышенный уровень сериализации для этой одной транзакции при ее создании (что вы делаете; это не так. не хак, просто как все делается в зависимости от ситуации).

...