SQL Server: как да придобия ексклузивно заключване за предотвратяване на състояние на състезание?

Имам следния 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

Има ли по-добър начин за придобиване на изключително заключване за цялата транзакция без подобни хакове?


person Novitzky    schedule 17.03.2011    source източник
comment
Не съм съвсем сигурен какво се опитвате да направите. Това ли ви трябва? sqlteam.com/article/   -  person Martin Smith    schedule 17.03.2011


Отговори (2)


Не съм съвсем сигурен какво се опитвате да направите от публикувания код. Предполагам, че просто се опитвате да сериализирате достъпа до тази част от кода? Ако е така, sp_getapplock трябва да направи това, от което се нуждаете, вместо да създава нова фиктивна таблица, която просто използвате, за да заключвате.

Подробности тук

person Martin Smith    schedule 17.03.2011

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

person KeithS    schedule 17.03.2011