≪
≫

Журнализация и буферизация

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

Если бы запись об изменении БД, которая должна поступить в журнал при выполнении любой операции модификации БД, реально немедленно записывалась бы во внешнюю память, это привело бы к существенному замедлению работы системы. Поэтому записи в журнал тоже буферизуются: при нормальной работе очередная страница выталкивается во внешнюю память журнала только при полном заполнении записями.

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

Проблема не возникает при индивидуальных откатах транзакций, поскольку в этих случаях содержимое оперативной памяти не утрачено и можно пользоваться данными как буфера журнала, так и буферов страниц БД. Но если произошел мягкий сбой, и содержимое буферов утрачено, для проведения восстановления БД необходимо иметь некоторое согласованное состояние журнала и БД во внешней памяти.

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

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

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

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

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

Рассмотрим теперь, как можно выполнять операции восстановления БД в различных ситуациях, если в системе поддерживается общий для всех транзакций журнал с общей буферизацией записей, поддерживаемый в соответствии с протоколом WAL.

 
Посмотреть оригинал