45888 (Deadlocks), страница 4

2016-07-31СтудИзба

Описание файла

Документ из архива "Deadlocks", который расположен в категории "". Всё это находится в предмете "информатика" из , которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "рефераты, доклады и презентации", в предмете "информатика, программирование" в общих файлах.

Онлайн просмотр документа "45888"

Текст 4 страницы из документа "45888"

Теперь переключимся во второе окно и выполним 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 на первую запись, все для того же самого – чтобы убедиться, подходит запись или нет. Первая запись не подходит, и блокировка снимается. А вторая запись уже эксклюзивно заблокирована транзакцией T2, которая успела влезть между двумя Update'ами. Вот тут-то и происходит взаимоблокировка.

Рисунок 2. Взаимоблокировка из-за многократного перебора записей.

Без излишних подробностей можно описать происходящее примерно так:

T1 перебирает все записи по очереди, сначала блокируя их (U), убеждается, что запись не нужна и снимает блокировку, до тех пор пока не найдет нужную (x = 4), после чего, поднимает блокировку до X и производит запись. И, что важно, эта блокировка уже не снимается, а висит до конца транзакции.

T2 делает тоже самое. Она начинает перебирать записи, ставя и снимая блокировки, пока не находит нужную (x = 2). После этого она выполняет те же самые действия, что и первая транзакция - конвертацию блокировки в X, а затем запись. Опять-таки, эта блокировка (X) (и только эта) удерживается до фиксации или отмены T2. После этого перебор записей продолжается, так как не известно, все ли подходящие записи выбраны. Рано или поздно T2 натыкается на запись, уже заблокированную T1 (x=4), и вынуждена ждать либо фиксации, либо отмены T1.

Стартует второй оператор T1, со своим перебором, и натыкается на запись, уже заблокированную эксклюзивно (X) транзакцией T2 (x = 2).

Таким образом, T1 ждет T2, которая ждет T1 – взаимоблокировка.

Примечательно, что если на втором шаге T2 наткнется на запись, заблокированную T1, раньше чем найдет хотя бы одну запись, удовлетворяющую ее условию, то никакой мертвой блокировки не случится, так как все блокировки обновления (U), снимаются тут же, не дожидаясь конца транзакции. А значит, T2 ничего не удерживает, и не сможет выполняться дальше, пока T1 не завершиться.

Убедиться в этом можно, поменяв UPDATE в T2 таким образом:

UPDATE Tbl SET X=10 WHERE X=10

и запустив заново скрипты. Перебирая записи по очереди, T2 раньше доберется до x=4, чем до x=10, и не сможет заблокировать x=10, а будет ждать, пока освободится x=4.

С другой стороны, если и T1 и T2 нашли нужную запись и успешно сконвертировали блокировку, то, что найдет раньше второй оператор в T1, уже значения не имеет. Он все равно вынужден перебрать все записи, и рано или поздно вынужден будет ожидать T2, которая уже ждет T1.

Способы устранения

Здесь опять-таки причина взаимоблокировки заключается в нарушении порядка доступа. Первая транзакция обращается дважды к одним и тем же записям, отпуская и снова накладывая блокировку. Если другая транзакция успевает захватить любой ресурс, вступив при этом в конфликт с первой, происходит взаимоблокировка. Это диктует способ лечения. Надо либо запретить второй транзакции втискиваться между первыми двумя, либо сделать так, чтобы они вообще не пересекались. В данном случае возможны следующие варианты:

Повысить уровень изоляции до SERIALIZABLE. При этом уровне изоляции все блокировки держатся до конца транзакции, таким образом, первый оператор T1 заблокирует до фиксации или отмены даже те записи, которые отбирались просто для проверки и под условие поиска не подпадали. Транзакция T2 будет вынуждена ждать в самом начале, не успев наложить ни одной блокировки, и не сможет помешать второму обновлению T1. А значит, сначала отработает T1 целиком, а потом уже T2.

С помощью специальной подсказки (hint) указать оптимизатору, что при обновлении записи блокировка должна производиться не по записям, а потаблично. Эффект будет тем же самым, что и при повышении уровня изоляции до SERIALIZABLE. T1 при первом же обращении заблокирует всю таблицу и будет удерживать блокировку до фиксации или отмены, а T2 не сможет захватить ни одну запись до тех пор, пока не отработает T1.

Построить индекс по X. В этом случае не будет никакой необходимости перебирать все записи по очереди. Пользуясь информацией из индекса, транзакции будут сразу обращаться к нужной записи. Таким образом, T1 и T2 никогда не понадобится одна и та же запись, и они не передерутся за ресурсы.

Очевидно, что третий вариант в подавляющем большинстве случаев предпочтительнее с точки зрения производительности.

Распределенная взаимоблокировка

Взаимоблокировка считается распределенной, если часть графа ожидания находится вне сервера. Можно выделить два типа.

1. Часть графа ожидания находится в клиентском приложении. Предположим, что группе клиентских потоков необходимо синхронизировать доступ к какому-либо ресурсу помимо СУБД. Один поток может захватить клиентский объект и ожидать снятия блокировки в БД. В это время другой поток, захвативший объект БД, необходимый первому потоку, может ожидать, пока первый поток освободит клиентский объект. Главная неприятность подобной взаимоблокировки в том, что она в принципе не детектируется, и приложение повисает намертво, если время ожидания блокировки не выставлено в разумных пределах. Можно порекомендовать следующие методы борьбы:

Использовать одно подключение к базе для всех потоков. В этом случае потоки на сервере не будут блокировать друг друга.

Microsoft SQL Server поддерживает механизм «связанных подключений» (BoundConnections), когда несколько подключений на клиенте «связываются» вместе и воспринимаются сервером как одно подключение. Эффект тот же самый, что и в предыдущем случае – потоки не блокируют друг друга при доступе к объектам СУБД.

Для синхронизации доступа к клиентскому объекту использовать механизм блокировок сервера. Некоторые серверы, в том числе и Microsoft SQL Server, имеют возможность предоставить свой менеджер блокировок для нужд внешних приложений. В этом случае весь граф ожидания находится на сервере, и определить взаимоблокировку не составляет никакого труда.

2. Часть графа ожидания находится на другом сервере баз данных. Тут, как ни странно, все еще сложнее. Для начала можно вспомнить, что не все серверы используют блокировки для синхронизации доступа. Тем не менее, даже если все участники транзакции – серверы, использующие блокировки, но разных производителей, все равно не обойтись без стандартного представления графа ожидания, который понимали бы все СУБД. Такового на данный момент не существует. И, наконец, даже если речь идёт только об одном сервере, то объём информации о графах ожидания, который нужно передавать по сети, может быть довольно значительным, хотя теоретически, в этом случае обнаружить взаимоблокировку можно. Можно было бы также построить механизм борьбы с распределенными взаимоблокировками на основе временных меток. Тогда объем информации, необходимый для предотвращения взаимоблокировки, был бы значительно меньше, но в случае большого числа откатов этот способ малоприменим. На данный момент Microsoft SQL Server не поддерживает определение распределенных взаимоблокировок между различными серверами.

Общие рекомендации

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

Лучший же способ избежать мертвых блокировок – это четко представлять себе, что делает сервер при тех или иных операциях, и не допускать стандартных и хорошо изученных ошибок.

В первую очередь необходимо придерживаться единого порядка доступа ко всем ресурсам. Причём имеется в виду и то, что транзакция не должна возвращаться к уже заблокированному ей же ресурсу для наложения более сильной блокировки. Другими словами, мы сразу накладываем самую сильную из нужных нам блокировок. При строгом соблюдении данного правила мертвые блокировки вообще невозможны. Другое дело, что оно накладывает достаточно сильные ограничения, и в большинстве случаев так не поступают, например блокировки обновления – вполне разумный компромисс.

Очень часто в различных performance tips рекомендуют везде, где только можно, устанавливать уровень изоляции в READ UNCOMMITED. Я бы хотел предостеречь от этого шага. Вероятность мертвой блокировки при использовании этого уровня изоляции, конечно, понизится, но риск привести базу в несогласованное состояние при этом возрастает многократно. Бороться с последствиями этого эффекта гораздо сложнее, чем с последствиями возникновения взаимоблокировки. В подавляющем большинстве случаев можно найти выход из ситуации, не используя этот уровень изоляции. Как правило, необходимость его использования является следствием ошибок проектирования.

Довольно часто рекомендуется использовать наиболее низкий уровень изоляции. По сути своей совет правильный, так как при этом уменьшается число ожидающих на блокировках транзакций, уменьшается время удерживания блокировок и, как следствие, уменьшается вероятность того, что различные транзакции схлестнутся в борьбе за ресурсы. Но, как было показано в предыдущем примере, возможны и исключения. Там взаимоблокировка произойдет при уровнях изоляции READ COMMITED и REPEATABLE READ, а при уровне изоляции SERIALIZABLE ее уже не случится. То же самое относится и к рекомендации блокировать как можно меньший объем. В большинстве случаев это действительно помогает, по тем же самым причинам: потенциально опасные транзакции с меньшей вероятностью захватят общие ресурсы, но опять-таки возможны исключения.

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5137
Авторов
на СтудИзбе
440
Средний доход
с одного платного файла
Обучение Подробнее