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




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

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

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

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

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

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

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

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

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

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

Основой обнаружения тупиковых ситуаций является построение (или постоянное поддержание) графа ожидания транзакций.

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

Например:

где P1, P2, P3 – параллельные транзакции, R – элемент обработки.

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

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

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

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

Для простоты изображения можно использовать другое определение графа ожидания.

Определение. Граф ожидания представляет собой ориентированный граф G¢ = (V¢, E¢), состоящий из множества вершин – определяющих выполняемые транзакций и множества ориентированных ребер или дуг – формируемых следующим образом:

5. Создается вершина, соответствующая каждой транзакции.

6. Создается дуга A → B, если транзакция A ожидает освобождение элемента данных, заблокированного в настоящее время транзакцией B.

Взаимоблокировка имеет место, если граф ожидания содержит цикл.

Например. Построим граф ожидания для примера взаимоблокировки при устранении проблемы потери результатов обновления (см. график выше).

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: