Deadlocks

Существуют и более удачный способ определения взаимоблокировок (хотя и более трудоемкий). Для этого менеджер блокировок строит направленный граф, который называется

Deadlocks

Информация

Компьютеры, программирование

Другие материалы по предмету

Компьютеры, программирование

Сдать работу со 100% гаранией

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

BEGIN TRAN

UPDATE Tbl SET X=4 WHERE X=4

WAITFOR DELAY '00:00:10'

UPDATE Tbl SET X=6 WHERE X=6

COMMIT TRAN

23:51:28.01 spid4 Requested By:

23:51:28.01 spid4 ResType:LockOwner Stype:'OR' Mode: U SPID:53

ECID:0 Ec:(0x19577548) Value:0x19333d60 Cost:(0/54)

23:51:28.01 spid4 Victim Resource Owner:

23:51:28.01 spid4 ResType:LockOwner Stype:'OR' Mode: U SPID:53

ECID:0 Ec:(0x19577548) Value:0x19333d60 Cost:(0/54)Здесь представлена информация о замкнутом цикле в графе ожидания, в цикл входят 2 узла (Node:1 и Node:2). Информация об узлах следующая: транзакции T2 (Node:1) нужна строка RID 7:1:50:1 для изменения (Requested By:\Mode U), владеет этой транзакцией процесс с идентификатором 51 (Requested By:\SPID:51). Однако на эту строку уже наложена эксклюзивная блокировка (Grant List:\Mode: X) процессом с идентификатором 53 (Grant List:\SPID: 53). Сама блокировка нужна, чтобы выполнить оператор UPDATE (Statement Type: UPDATE). Далее идет текст пакета, в котором блокировка была запрошена. Точно так же описан и второй узел графа, только там нужна строка RID 7:1:50:3, которой владеет транзакция, уже описанная в первом узле.

Отсюда становится понятно, за какие ресурсы передрались эти транзакции. Но зачем при выполнении оператора UPDATE транзакции T1 потребовалась строка, которой уже владеет T2 (как было уже замечено, по условиям они не пересекаются), пока не ясно. И при этом непонятно, почему T2 удерживала блокировку ведь по идее она должна была отработать и зафиксироваться, или откатиться, но блокировку снять. Поскольку других транзакций в это время не работало, значит, виновата та же T1.

Анализ ситуации

Разобраться в том, что происходит дальше, поможет недокументированный флаг трассировки 1200, который выдает всю последовательность наложения блокировок.

ПРИМЕЧАНИЕ

Вообще-то ту же самую информацию можно получить вполне законным способом, используя все тот же SQL Profiler, но дабы не загромождать описание особенностями работы с этой программой, здесь мы будем использовать недокументированный флаг трассировки.Запустим первую часть T1 (до WAITFOR), предварительно выставив флаг трассировки, и посмотрим, что за блокировки и в каком порядке накладываются.

DBCC TRACEON(1200, 3604, -1)

GO

BEGIN TRAN

UPDATE Tbl SET X = 4 WHERE X = 4Получим примерно следующую картину, с точностью до констант:

Process 53 acquiring IX lock on TAB: 6:2034106287 [] (class bit2000000 ref1) result: OK

Process 53 acquiring IU lock on PAG: 6:1:17495 (class bit0 ref1) result: OK

Process 53 acquiring U lock on RID: 6:1:17495:0 (class bit0 ref1) result: OK

Process 53 releasing lock on RID: 6:1:17495:0

Process 53 acquiring U lock on RID: 6:1:17495:1 (class bit0 ref1) result: OK

Process 53 releasing lock on RID: 6:1:17495:1

Process 53 acquiring U lock on RID: 6:1:17495:2 (class bit0 ref1) result: OK

Process 53 releasing lock on RID: 6:1:17495:2

Process 53 acquiring U lock on RID: 6:1:17495:3 (class bit0 ref1) result: OK

Process 53 acquiring IX lock on PAG: 6:1:17495 (class bit2000000 ref1) result: OK

Process 53 acquiring X lock on RID: 6:1:17495:3 (class bit2000000 ref1) result: OK

Process 53 releasing lock reference on RID: 6:1:17495:3

Process 53 acquiring S lock on RID: 6:1:17495:3 (class bit0 ref1) result: OK

Process 53 releasing lock reference on RID: 6:1:17495:3

Process 53 releasing lock reference on RID: 6:1:17495:3

Process 53 acquiring U lock on RID: 6:1:17495:4 (class bit0 ref1) result: OK

Process 53 releasing lock on RID: 6:1:17495:4

.......

Process 53 acquiring U lock on RID: 6:1:17495:9 (class bit0 ref1) result: OK

Process 53 releasing lock reference on PAG: 6:1:17495

Process 53 releasing lock on RID: 6:1:17495:9Сначала сервер накладывает эксклюзивную блокировку намерения IX на таблицу Tbl (TAB 6:2034106287), поскольку в эту таблицу собирается записывать. Далее накладывается блокировка намерения обновления IU на первую страницу в таблице (PAG 6:1:17495). Поскольку в этой таблице нет индекса, то, чтобы найти нужную запись, необходимо прочитать по очереди все записи, входящие в таблицу, а чтобы прочитать запись, ее надо предварительно заблокировать, что мы и наблюдаем.

Process 53 acquiring U lock on RID: 6:1:17495:0Обратите внимание, здесь, считывая запись для проверки, сервер накладывает блокировку обновления. Если запись удовлетворит условию выборки, можно будет сконвертировать блокировку в эксклюзивную, не опасаясь возможной взаимоблокировки. Как только сервер убеждается, что запись не подходит, блокировка снимается. На данном уровне изоляции сервер имеет на это полное право, добиваясь тем самым более высокой степени параллелизма.

Process 53 releasing lock on RID: 6:1:17495:0Как только находится нужная запись, блокировка на страницу конвертируется в IX:

Process 53 acquiring IX lock on PAG: 6:1:17495затем блокировка на запись конвертируется в X:

Process 53 acquiring X lock on RID: 6:1:17495:3и производится изменение записи. Блокировка этой записи, естественно, до конца транзакции не снимается.

Поскольку сервер не знает, что он уже выбрал все записи, удовлетворяющие условию, то он продолжает перебирать по очереди все, что осталось, накладывая и снимая соответствующую блокировку на каждую запись. Если после выполнения этой части транзакции посмотреть на наложенные блокировки, то мы увидим эксклюзивную блокировку записи x = 4 (RID 1:17495:3) и эксклюзивные блокировки намерения выше по иерархии, на страницу и таблицу:

dbid ObjId ObjName Type Resource Mode Status

------ ----------- ------- ---- ---------- ----- -------

6 2034106287 Tbl RID 1:17495:3 X GRANT

6 2034106287 Tbl PAG 1:17495 IX GRANT

6 2034106287 Tbl TAB IX GRANT Как и следовало ожидать, больше подходящих записей не нашлось, ничего не обновилось, а значит, других блокировок удерживать не надо.

Теперь переключимся во второе окно и выполним T2, также с выставленным флагом отслеживания порядка наложения блокировок:

DBCC TRACEON(1200, 3604, -1)

BEGIN TRAN

UPDATE Tbl SET X = 2 WHERE X = 2

COMMIT TRAN

DBCC TRACEOFF(1200, 3604, -1)Затем переключимся обратно в первое окно и завершим выполнение первой транзакции:

UPDATE Tbl SET X = 6 WHERE X = 6

COMMIT TRAN

DBCC TRACEOFF(1200, 3604, -1)После этого произойдет мертвая блокировка, о чем сервер нам и сообщит.

Переключимся опять в окно с T2 (надеюсь, эти скачки не слишком утомительны) и посмотрим, каков был порядок наложения блокировок в T2:

Process 51 acquiring IX lock on TAB: 6:2034106287 [] (class bit2000000 ref1) result: OK

Process 51 acquiring IU lock on PAG: 6:1:17495 (class bit0 ref1) result: OK

Process 51 acquiring U lock on RID: 6:1:17495:0 (class bit0 ref1) result: OK

Process 51 releasing lock on RID: 6:1:17495:0

Process 51 acquiring U lock on RID: 6:1:17495:1 (class bit0 ref1) result: OK

Process 51 acquiring IX lock on PAG: 6:1:17495 (class bit2000000 ref1) result: OK

Process 51 acquiring X lock on RID: 6:1:17495:1 (class bit2000000 ref1) result: OK

Process 51 acquiring U lock on RID: 6:1:17495:2 (class bit0 ref1) result: OK

Process 51 releasing lock on RID: 6:1:17495:2

Process 51 acquiring U lock on RID: 6:1:17495:3 (class bit0 ref1) result: OKWAIT

Process 51 releasing lock on RID: 6:1:17495:3

Process 51 acquiring U lock on RID: 6:1:17495:4 (class bit0 ref1) result: OK

Process 51 releasing lock on RID: 6:1:17495:4

..........Начало такое же, как и в T1, что, в общем, закономерно: IX на таблицу, IU на страницу. Затем U на первую запись, чтобы затем прочитать и выяснить, подходит она нам или нет. Если не подходит, снимаем блокировку и переходим к следующей записи.

Следующая запись подходит, и начинается тот же процесс, что и в первом запросе T1. Конвертируем блокировку на страницу в IX, на запись в эксклюзивную (X), и производим обновление. Эта блокировка, как и в T1, не снимается. Опять же, поскольку сервер не знает, что он выбрал все записи, удовлетворяющие условию, указанному в WHERE, то он продолжает перебирать оставшиеся записи по очереди. Вот тут и начинаются отличия: Запись X = 4 (RID 6:1:17495:3) удерживается эксклюзивной блокировкой (X), наложенной T1, ведь T1 мы не зафиксировали. И как только T2 доберется до этой записи, то она будет вынуждена ждать на блокировке до тех пор, пока T1 не отменится или не зафиксируется, так как U и X блокировки не совместимы, что мы и наблюдаем:

Process 51 acquiring U lock on RID: 6:1:17495:2 (class bit0 ref1) result: OKWAITЭто ожидание длится до фиксации или, как в нашем случае, до отмены T1. Дальнейшие записи уже относятся к состоянию, когда T1 отменена, и в них нет ничего интересного, такой же последовательный перебор записей входящих в таблицу.

Теперь переключимся в первое окно к T1 и посмотрим, что происходило после старта второй части этой транзакции:

Process 53 acquiring IU lock on PAG: 6:1:17495 (class bit0 ref1) result: OK

Process 53 acquiring U lock on RID: 6:1:17495:0 (class bit0 ref1) result: OK

Process 53 releasing lock on RID: 6:1:17495:0

Process 53 acquiring U lock on RID: 6:1:17495:1 (class bit0 ref1) result: TIMEDOUT

Process 53 sleeping for lock

Process 53 acquiring U lock on RID: 6:1:17495:1 (class bit0 ref1) result: DEADLOCKЗапрашивается IU на страницу и U на первую запись, все для того же самого чтобы убедиться, подходит запись или нет. Первая з

Похожие работы

<< < 1 2 3 4 5 6 7 > >>