Журнализация
изменений тесно связана не только с управлением транзакциями, но и с буферизацией
страниц базы данных в оперативной памяти.
Если бы запись
об изменении базы данных, которая должна поступить в журнал при выполнении любой
операции модификации базы данных, реально немедленно записывалась бы во внешнюю
память, это привело бы к существенному замедлению работы системы. Поэтому записи
в журнале тоже буферизуются: при нормальной работе очередная страница выталкивается
во внешнюю память журнала только при полном заполнении записями.
Проблема
состоит в выработке некоторой общей политики выталкивания, которая обеспечивала
бы возможность восстановления состояния базы данных после сбоев.
Проблема
не возникает при индивидуальных откатах транзакций, поскольку в этих случаях
содержимое оперативной памяти не утрачено и можно пользоваться содержимым как
буфера журнала, так и буферов страниц базы данных. Но если произошел мягкий
сбой и содержимое буферов утрачено, для проведения восстановления базы данных
необходимо иметь некоторое согласованное состояние журнала и базы данных во
внешней памяти.
Основным
принципом согласованной политики выталкивания буфера журнала и буферов страниц
базы данных является то, что запись об изменении объекта базы данных должна
попадать во внешнюю память журнала раньше, чем измененный объект оказывается
во внешней памяти базы данных. Соответствующий протокол журнализации (и управления
буферизацией) называется Write Ahead Log (WAL) — «пиши сначала в журнал»
и состоит в том, что если требуется записать во внешнюю память измененный объект
базы данных, то перед этим нужно гарантировать запись во внешнюю память журнала
транзакций записи о его изменении.
Другими словами,
если во внешней памяти базы данных находится некоторый объект базы данных, по
отношению к которому выполнена операция модификации, то во внешней памяти журнала
обязательно находится запись, соответствующая этой операции. Обратное неверно,
то есть если во внешней памяти журнале содержится запись о некоторой операции
изменения объекта базы данных, то сам измененный объект может отсутствовать
во внешней памяти базы данных.
Дополнительное
условие на выталкивание буферов накладывается тем требованием, что каждая успешно
завершившаяся транзакция должна быть реально зафиксирована во внешней памяти.
Какой бы сбой не произошел, система должна быть в состоянии восстановить состояние
базы данных, содержащее результаты всех зафиксированных к моменту сбоя транзакций.
Простым решением
было бы выталкивание буфера журнала, за которым следует массовое выталкивание
буферов страниц базы данных, изменявшихся данной транзакцией. Довольно часто
так и делают, но это вызывает существенные накладные расходы при выполнении
операции фиксации транзакции.
Оказывается,
что минимальным требованием, гарантирующим возможность восстановления последнего
согласованного состояния базы данных, является выталкивание при фиксации транзакции
во внешнюю память журнала всех записей об изменении базы данных этой транзакцией.
При этом последней записью в журнал, производимой от имени данной транзакции,
является специальная запись о конце транзакции.
Рассмотрим
теперь, как можно выполнять операции восстановления базы данных в различных
ситуациях, если в системе поддерживается общий для всех транзакций журнал с
общей буферизацией записей, поддерживаемый в соответствии с протоколом WAL.