ВВЕДЕНИЕ В СИСТЕМЫ УПРАВЛЕНИЯ БАЗАМИ ДАННЫХ

       

Разрешение тупиковых ситуаций


Итак, при использовании протокола доступа к данным с использованием блокировок часть проблем разрешилось (не все), но возникла новая проблема - тупики:

  • Проблема потери результатов обновления - возник тупик.
  • Проблема незафиксированной зависимости (чтение "грязных" данных, неаккуратное считывание) - проблема разрешилась.
  • Неповторяемое считывание - проблема разрешилась.
  • Появление фиктивных элементов - проблема не разрешилась.
  • Проблема несовместимого анализа - возник тупик.

    Общий вид тупика (dead locks) следующий:

    Транзакция A

    Время

    Транзакция B



    Ожидание…

    Ожидание…

    Блокировка объекта
    - успешна
    ---
    ---
    Блокировка объекта
    -успешна
    Блокировка объекта
    - конфликтует с блокировкой, наложенной транзакцией B
    ---
    Ожидание…
    Блокировка объекта
    - конфликтует с блокировкой, наложенной транзакцией A
    Ожидание…
    Ожидание…
     

    Как видно, ситуация тупика может возникать при наличии не менее двух транзакций, каждая из которых выполняет не менее двух операций. На самом деле в тупике может участвовать много транзакций, ожидающих друг друга.

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

    Можно представить два принципиальных подхода к обнаружению тупиковой ситуации и выбору транзакции-жертвы:

  • СУБД не следит за возникновением тупиков. Транзакции сами принимают решение, быть ли им жертвой.
  • За возникновением тупиковой ситуации следит сама СУБД, она же принимает решение, какой транзакцией пожертвовать.

    Первый подход характерен для так называемых настольных СУБД (FoxPro и т.п.). Этот метод является более простым и не требует дополнительных ресурсов системы. Для транзакций задается время ожидания (или число попыток), в течение которого транзакция пытается установить нужную блокировку.
    Если за указанное время ( или после указанного числа попыток) блокировка не завершается успешно, то транзакция откатывается (или генерируется ошибочная ситуация). За простоту этого метода приходится платить тем, что транзакции-жертвы выбираются, вообще говоря, случайным образом. В результате из-за одной простой транзакции может откатиться очень дорогая транзакция, на выполнение которой уже потрачено много времени и ресурсов системы.

    Второй способ характерен для промышленных СУБД (ORACLE, MS SQL Server и т.п.). В этом случае система сама следит за возникновением ситуации тупика, путем построения (или постоянного поддержания) графа ожидания транзакций. Граф ожидания транзакций - это ориентированный двудольный граф, в котором существует два типа вершин - вершины, соответствующие транзакциям, и вершины, соответствующие объектам захвата. Ситуация тупика возникает, если в графе ожидания транзакций имеется хотя бы один цикл. Одну из транзакций, попавших в цикл, необходимо откатить, причем, система сама может выбрать эту транзакцию в соответствии с некоторыми стоимостными соображениями (например, самую короткую, или с минимальным приоритетом и т.п.).


    Содержание раздела