Блокировок, естественно, добавилось:
spid dbid
ObjId ObjName IndId Type
Resource Mode Status
------
------ ----------- ------- ------ ---- ---------- ----- -------
54 6
2034106287 Tbl 0 PAG 1:17495 IS
GRANT
54 6
2034106287 Tbl 0 RID 1:17495:1 S
GRANT
54 6
2034106287 Tbl 0 TAB
IS GRANT
61 6
2034106287 Tbl 0 PAG 1:17495 IX
GRANT
61 6
2034106287 Tbl 0 RID 1:17495:1 X
CNVT
61 6
2034106287 Tbl 0 TAB
IX GRANT
|
Те, что (в моем случае) от spid 54 – это наложенные
ранее, от первой транзакции, а те, у которых spid 61 - от второй. С
блокировками намерения все то же самое, они запрошены и успешно получены. А вот
с эксклюзивными ситуация такая: сначала, выполняя SELECT, мы получили
разделяемую блокировку на ту же запись (RID 1:17495:1), что и первая
транзакция. Затем нам понадобилось туда же записать, а для этого надо
сконвертировать коллективную блокировку S до X. Однако сделать это не
получается, так как мешает S-блокировка на ту же запись от первой транзакции.
Что мы и видим в третьей снизу строчке, статус эксклюзивной блокировки (X) CNVT
– конвертирование. То есть SELECT выполнился, но до UPDATE дело не дошло, T2
ждет, пока T1 освободит запись X=2, чтобы наложить эксклюзивную блокировку.
Переключимся обратно в первое окно и попытаемся
завершить T1:
UPDATE Tbl SET Y=3 WHERE X=2
COMMIT TRAN
|
Теперь и T1 будет ждать, пока T2 освободит свою
коллективную блокировку. Таким образом, транзакции будут ожидать друг друга, цикл в графе ожидания замкнется и, некоторое время спустя, когда менеджер
блокировок это обнаружит, одна из транзакций будет отменена. Приложение, запустившее ее, получит сообщение 1205 о взаимоблокировке (Transaction
(Process ID 61) was deadlocked on lock resources with another process and has
been chosen as the deadlock victim. Rerun
the transaction), а другая транзакция завершится успешно.
В сущности, мы здесь имеем дело опять-таки с
нарушением порядка доступа, но несколько в иной форме. Сначала транзакция
наложила слабую блокировку на ресурс, а потом вернулась к этому же ресурсу, чтобы наложить более сильную. Особенность этой достаточно часто встречающейся
ситуации в том, что это не две разных транзакции, а одна и та же, просто
запущенная из разных сессий.
Способы устранения
Поскольку взаимоблокировка произошла из-за того, что
транзакции удерживали коллективные блокировки и потом попытались их повысить до
эксклюзивных, то, в принципе, помочь избежать неприятностей в данном случае
сможет понижение уровня изоляции до READ COMMITED. При этом коллективная
блокировка не будет держаться до конца транзакции, а снимется сразу после
завершения чтения, а значит, обновить записи ничто не помешает. Но тогда вместо
взаимоблокировки мы вполне можем получить неверные данные, так как между SELECT
и UPDATE сможет втиснуться другая транзакция, которая изменит Y и данные, полученные SELECT’ на момент UPDATE, окажутся неактуальными, чего в некоторых
случаях допускать нельзя.
Можно также сразу при чтении наложить эксклюзивную
блокировку, но это тоже не самый лучший выход с точки зрения
производительности, так как могут существовать транзакции, которым эти данные
надо просто прочитать, а наложение эксклюзивной блокировки увеличивает время их
пассивного ожидания.
В общем случае наилучшим выходом здесь будет наложение
при чтении промежуточной блокировки обновления. Такая блокировка совместима с
коллективной, что позволит читающим транзакциям обращаться кэтим данным беспрепятственно.
А когда понадобится их обновить, то проблем быть не должно, так как блокировки
обновления между собой несовместимы, и значит, другие транзакции, читающие эти
данные для последующего изменения (и естественно тоже запросившие их с блокировкой
обновления), будут ждать, пока эти данные поменяются, никому не мешая. Для
этого необходимо изменить первый оператор транзакции примерно таким образом:
SELECT
@Var = Y FROM Tbl WITH (UPDLOCK) WHERE X = 2
|
Третий пример
К сожалению, взаимоблокировки в реальных приложениях
не так тривиальны, и выяснить реальную причину их возникновения бывает
достаточно сложно, так как одну из виновных транзакций пристреливают, и
приложение работает дальше, оставляя лишь небольшое и малоинформативное
сообщение об ошибке. Попробуем разобрать немного более сложный случай в
условиях, максимально приближенных к боевым, и попытаемся понять поведение
сервера, приведшее к тупиковой ситуации.
Рекомендуем скачать другие рефераты по теме: урок изложение, диплом разработка.
Предыдущая страница реферата |
4
5
6
7
8
9
10
11
12
13
14 |
Следующая страница реферата