2010 г.
Взаимные блокировки в Oracle
Сергей Жилин, январь – март 2010 года
http://dba.ucoz.ru
Содержание
- Граф ожидания транзакций
- Сценарии возникновения
- Блокировки транзакций. Захват и ожидание в исключительном
режиме.
- Блокировки транзакций. Захват в исключительном и ожидание в
разделяемом режимах.
- Блокировки на уровне таблицы.
- Хранимые PL/SQL объекты
- Процедура
- Исключения
- Заключение
- Список литературы
Взаимная блокировка (deadlock) —
это ситуация в СУБД, при которой двое или
более сеансов находятся в состоянии бесконечного ожидания ресурсов,
захваченных самими этими же сеансами. При обычном состоянии, когда
один из сеансов захватывает какой-либо ресурс, другие сеансы будут
ожидать его освобождения, выстраиваясь в очередь друг за другом.
Но если удерживающий сеанс не может освободить ресурс вследствие
того, что он ожидает освобождения ресурса, захваченного одним из
ожидающих сеансов, возникает парадоксальная ситуация, при которой
ни один из захваченных сеансами ресурсов не может быть освобождён.
В этом случае СУБД сама должна вмешаться в процесс бесконечного
ожидания и принудительно освободить запрос в сеансе к одному из
ресурсов. При этом никак не должна пострадать уже начатая
транзакция сеанса. СУБД должна только отменить последнее действие в
сеансе, которое привело к сложившейся ситуации взаимного
блокирования, и предоставить сеансу решить, зафиксировать ли
изменения в данных или отменить их.
Надо сказать, что возникновение взаимного
блокирования — это исключительный случай для СУБД. У Oracle даже для
этого случая есть специальная ошибка ORA-00060. Если взаимные
блокировки возникают очень редко, то можно просто игнорировать эту
ошибку, обрабатывая данное исключение в приложении. Но когда
подобная ошибка начинает возникать очень часто, требуется детальный
анализ возникающей ситуации. Большую помощь в этом нам может
оказать файл трассировки, который создаёт Oracle в каждом случае
возникновения взаимных блокировок. Образуется этот файл в каталоге,
который определяется параметром инициализации user_dump_dest. Кроме
создания файла, Oracle делает также запись о возникшей ошибке в
системном журнале alert.log. В этом журнале, наряду с самим фактом
происшедшей ошибки, записывается ссылка к образованному файлу
трассировки. Так как данный журнал и файл доступны только
администратору базы данных, одним из пунктов его обязанностей должно являться обнаружение подобных записей и предоставление
разработчику приложения всей доступной информации для исправления
повторяющихся взаимных блокировок.
Граф ожидания транзакций
Прежде чем начинать подробно изучать устройство
взаимной блокировки, попробуем разобраться в том, как Oracle
обнаруживает ситуации взаимного блокирования. В будущем это
позволит нам проще понять этот механизм при некоторых сложных
сценариях развития взаимной блокировки, а также позволит лучше
ориентироваться в содержимом трассировочного файла взаимного
блокирования.
В Oracle, как и в других современных
СУБД, поиск ситуаций взаимного блокирования происходит постоянно.
Вначале строится так называемый граф ожидания транзакций. Граф
состоит из вершин и соединяющих их рёбер. Существуют два типа
вершин – это вершины, соответствующие транзакциям или сеансам,
и вершины, представляющие из себя ресурсы или объекты. Ребра в
данном случае представляют собой блокировки. Если блокировка
установлена, то ребро направлено от вершины соответствующей сеансу к
вершине, определяющей ресурс. Если же ожидается установка блокировки,
то наоборот ребро направлено от вершины ресурса к вершине,
соответствующей сеансу. Если в этом сплетении рёбер и вершин
обнаруживается цикл, то это означает, что возникла ситуация
взаимного блокирования. При этом Oracle должен выбрать и отменить
одно из ожидающих рёбер, что приведёт к разрыву цикла и
нормализации ситуации.
В дальнейшем для некоторых сложных сценариев
взаимной блокировки мы будем приводить схематическое изображение
графа ожидания транзакций, что позволит нам увидеть взаимную
блокировку в графическом виде.
Содержание Вперёд