Восстановление распределённых БД
Для распределённых СУБД выделяют следующие типы основных отказов, их немного:
1. Потеря сообщения,
2. Отказ линии связи, аварийная
3. Остановка одного из узлов,
4. Расчленение сети.
Для того, чтобы вот как-то в такой среде правильно восстанавливать данные, есть специальные процедуры – процедуры восстановления. При этом проблема в распределённой среде усложняется тем, что требования атомарности значений требуются как в отношении локальных, так и в отношении глобальных данных и глобальных транзакций.
Рассмотрим 2 протокола:
1. протокол ликвидации;
2. протокол восстановления.
Начнём с протокола ликвидации. Итак: что такое протокол ликвидации, когда он запускается? Он запускается всякий раз, когда координатор или узел не получит ожидаемого сообщения — тайм-аут (т.е. есть некая задержка, в течение которой координатор транзакции или любой из узлов не получит соответствующего сообщения). Тайм-аут возможен в 2-х случаях из 4-х.
Многие предпринимаемые действия зависят от того, кто из них не получил сообщения, и какое именно сообщение не было получено. Рассмотрим отдельно координатор и отдельно узел.
И так вот для координатора транзакций. И так при фиксации координатор в процессе выполнения фиксации находится в одном из 4 состояний: Initial, Waiting, Decided, Completed.
Делается команда prepare (Подготовиться), выдается команда global decision, а потом подтверждение.
Значит time out в режиме (состоянии) Waiting: Координатор ожидает подтверждения от всех узлов уведомления о решении об откате или фиксации своих подтранзакций. Поскольку узлов много, координатор координатор рассылает всем команду зафиксировать транзакцию. И каждый из узлов в зависимости от того там в каком состоянии он находится фиксирует или не фиксирует свою подтранзакцию. Если он в оговоренное время не получит подтверждение на фиксацию транзакций от всех, он должен запустить протокол ликвидации.
time out состоянии Decided: time out в этом случае фактически означает ожидание поступления от всех узлов уведомления о подтверждении фиксации. Здесь они ему говорят «будем мы фиксировать или нет?», а дальше он им посылает, если от всех получил подтверждение, он им говорит «фиксируйте!», потому что каждый из отдельных узлов не знает будет ли транзакция зафиксирована или нет. Каждый из них голосует первоначально за себя, что «Я готов!». То есть на этом уровне каждый из них присылает сообщение, что «Я готов!». Если координатор получил такое сообщение от всех, то далее идёт команда «фиксировать транзакцию», в противном случае, как я сказал, протокол ликвидации. Так вот далее идёт время на то чтобы они подтвердили транзакцию, при этом суть заключается в том, что если как-либо из узлов в этот момент не зафиксирует транзакцию, то, формально говоря, проблема остается в нем и его там надо соответствующим образом либо перезапускать, либо останавливать и так далее и так далее… но все остальные уже так или иначе зафиксированы.
Узел
У узла тоже еcть режим инициализации (Initial). Следующее состояние в котором он может находиться PREPARED. Далее либо подтверждение COMMITED, либо ABORTED.
У него есть time out в состоянии Initial. В этом состоянии узел ждёт от координатора поступления команды PREPARE(приготовиться). Если эта команда не поступает от координатора, то узел имеет право выполнить односторонний откат транзакции.
time out в состоянии PREPARED. Узел уже послал координатору свое сообщение, что он готов подтвердить транзакцию, ну по крайней мере, свою локальную часть и ждёт, когда координатор соберёт со всех такие сообщения и примет общее для всех решение подтвердить или отменить транзакцию. Значит вот здесь он ждёт. На самом деле в этом случае если возможен откат транзакции, то имеется возможность обратиться к соседнему узлу и спросить «а как у нас там?», «каково решение у нас там принято???». То есть вот такого рода действия узлов между собой называется корпоративный протокол ликвидации.
Протокол восстановления
Протокол восстановления запускается каждый раз, когда необходимо восстановить работу узла после его отказа. Предпринимаемые действия зависят от того кто отказал: узел или координатор. Немножко по порядку пойдём.
Отказ координатора в состоянии Initial. То есть он ещё не инициализировал глобальную фиксацию транзакций, то есть он отказал. Восстановление заключается в запуске этой процедуры заново.
Второе. Отказ координатора в состоянии Waiting. Координатор направил команду опроса узлов. «Готовы зафиксировать транзакцию или не готовы (свою локальную)?» Но ничего не получил с узлов по каким-то причинам. В этом случае отказ. Восстановление заключается в повторном запуске процедуры фиксации транзакции.
Отказ координатора в состоянии Decided. Координатор уже направил сообщение о глобальной фиксации или отказе. Поэтому здесь надо просто перезапустить координатор. Если после перезапуска он получит все необходимые подтверждения, то можно считать что транзакция завершилась успешно, если не получит после перезапуска, то надо преступить к протоколу ликвидации. Что касается узла.
Отказ узла в состоянии Initial. В этом случае узел ещё не проголосовал.
Отказ узла
Поскольку узел еще не проголосовал по поводу завершения транзакции, он имеет право принять односторонний отказ ,и если все хорошо – проголосовать за подтверждение транзакции. Отказ узла в состоянии PREPARED, фактически это означает, что узел уже отправил координатору сообщение о том, что он готов подтвердить транзакцию. Если он это отослал, и после этого произошел отказ, возникает проблема восстановления данных на этом конкретном узле. Естественно, что отказ может произойти в любой момент, и после голосования, и потом что то у него могло сбиться, после этого все будут подтверждать транзакцию, и он тоже, по идее должен, подтверждать, но если он ее подтвердить не может, значит здесь надо запускать протокол ликвидации отдельного узла, восстановление данных, все же остальные данные уже подтвердят, и отменить здесь ничего нельзя.
Отказ узла в состоянии ABORTED или COMMITED.
Это означает:
В COMMITED: узел уже подтвердил транзакцию свою, а потом ее фактически отменил, если после этого что то произошло, то формально говоря, никаких действий общих принимать не надо, потому что данные сохранены, и если сломалось что-то в компе, то в на сеть это не повлияет. На практике, в хорошо работающих системах вероятность блокировки одних узлов другими, не так высока, то был предложен протокол трех фазной фиксации, который в данном случае называется не блокирующим, который приводит к блокировке транзакции только в одном случае, всех узлов, что мало вероятно. Для нормальной работы такой распределенной среды, фактически достаточно, чтобы хотя бы один узел был доступен. Основная идея такой трехфазной фиксации заключается в устранении неопределенного периода ожидания, когда он блокирует работу. Вводится третья фаза, которая называется предфиксация, которая находится между фазами голосования и принятия глобального решения.
Вводится дополнительное сообщение, глобальное — ПРЕКОМИТ. Оно означает, что каждый узел теперь знает, что все проголосовали за фиксацию транзакции, и если что то произойдет на отдельном узле, то это проблемы того узла, и они будут решаться локально.