Россия |
Транзакции в базах данных
6.5 Транзакции, откаты и восстановление после сбоев
Требование атомарности транзакций означает, что откатившиеся транзакции или транзакции, не успевшие завершиться, не должны оставлять никаких следов своей работы в базе данных.
Требование долговечности означает, что данные, полученные зафиксированными транзакциями, должны сохраниться в базе, даже если в следующий за подтверждением момент произойдет сбой.
При современном уровне развития вычислительной техники единственный способ достичь приемлемой производительности это буферизация данных в оперативной памяти. Кажущийся естественным, способ немедленной записи данных завершенных транзакций на диск неприемлем, так как данные базы хранятся в файлах с адресным доступом, медленных по своей природе.
Выход из положения — использование дополнительных кольцевых последовательных буферов отката и файлов журналов, имеющих последовательный доступ. Такие файлы быстрее файлов данных. Избыточность, образующаяся при введении буферов отката и файлов журналов, позволяет хранить в базе и измененные данные, и их версии, существовавшие до внесения изменений. Рассмотрим работу буферных структур, изображенных на рисунке 6.8.
Кэш буферов базы — это раздел памяти (вспоминаем, что термин "память" означает "оперативная память" или "первичная память"), разделенный на блоки, по размеру совпадающие с блоками базы. Блок, который прочитали с диска и не успели изменить, называется чистым. И он же, но с внесенными изменениями, называется грязным. Заметим, что повышение быстродействия при использовании буферов базы происходит, только если вместе с необходимыми данными из диска извлекаются те данные, которые будут в ближайшее время использованы. Вспомните, что показатель HitRatio, определяемый как отношение числа обращений в буфер к общему числу обращений, очень близок к единице.
На самом деле чистые блоки пишутся одновременно и в кэш буферов базы, и в буфер журнала. Из-за высокого быстродействия первичной памяти это не слишком увеличивает время записи.
Кольцевой буфер отката состоит из таких же по размеру блоков. Из рисунка 6.8 видно, как взаимодействуют транзакции при квазипараллельной работе. Транзакция, например Т1, занимает чистыми блоками последовательно расположенные блоки буфера отката. Если в это время другая транзакция Т2 читает свой блок, то он будет размещен сразу за блоками, занятыми Т1, и далее блоки разных транзакций могут чередоваться. Если необходимо восстановить исходные данные, достаточно, используя инвертированные списки блоков, вытащить блоки откатываемой транзакции из кольцевого буфера. Движение по ссылкам занимает очень мало времени. Поэтому откат выполняется быстро.
Для того, чтобы сохранить изменения в базе, грязные блоки необходимо как можно скорее записать (как говорят, вытолкнуть) во вторичную память. Но при этом может резко упасть быстродействие. Поскольку последовательный файл журнала работает быстрее адресного файла данных, может оказаться, что запись в файл журнала выполнена, а запись в файл данных не успела завершиться, в этом случае файл данных будет восстановлен по файлу журнала.
6.5.1 Восстановление данных
Основные ситуации, в которых требуется восстановление данных:
- Откат транзакции по команде ROLLBACK.
- Мягкий сбой системы (утрата части или всей первичной памяти).
- Жесткий сбой системы (отказ аппаратуры, чаще повреждение вторичной памяти).
Далее будет рассмотрена упрощенная система организации откатов и восстановлений после сбоев.
Необходимо удовлетворить два противоречивых требования. С одной стороны, из-за недостатка оперативной памяти и из-за возможности сбоев необходимо выталкивать "грязные" блоки как можно раньше, но это замедлит работу. Для ускорения работы необходимо записывать на диск как можно реже, но это увеличивает риск рассогласования базы.
6.5.2 Принцип "Write Ahead Log"
Измененные объекты базы данных должны попадать в файл журнала раньше, чем грязные блоки кэша буферов базы попадут в файлы данных. Пиши сначала в журнальный файл! Write Ahead Log!
При этом может оказаться, что на диске имеется запись журнала, но еще нет записи блока базы. Если же записан блок данных, то журнальный блок тем более записан.
Периодически или при достижении кэшем буферов базы определенного состояния (например, количество страниц в списке грязных блоков превысило порог) возбуждается событие контрольной точки.
При этом выполняются следующие два действия:
- во внешнюю память выталкивается часть "грязных" блоков;
- во внешнюю память записывается контрольная точка, то есть список всех выполняемых в этот момент транзакций.
При выполнении одной транзакции восстановление последнего согласованного состояния базы гарантируется, если в файл журнала вытолкнуты все записи об изменении базы данных этой транзакцией, включая запись о конце транзакции.
6.5.3 Откат транзакции
Завершенные по COMMIT транзакции нельзя откатить. Для выполнения отката незавершенной транзакции необходимо:
- идя по инвертированному списку блоков занятых транзакцией, последовательно восстановить значения измененных блоков;
- при успешном завершении отката в журнал занести запись о завершении транзакции откатом.
6.5.4 Восстановление после мягкого сбоя
Пусть создана ситуация: принята последняя контрольная точка, и через некоторое время произошел мягкий сбой. Несколько возможных вариантов поведения системы:
- Транзакция успешно завершена до контрольной точки, все ее данные сохранены на диске. В восстановлении не нуждается.
- Транзакция успешно завершена. Блоки журнала вытолкнуты полностью, а блоки буферов базы частично. Необходимо завершить операции, не отображенные в блоках данных.
- Транзакция начата до последней контрольной точки и не завершилась до сбоя. Часть блоков данных и журнала переписана на диск по событию контрольной точки. Результатов остальных изменений нет. Необходимо откатить транзакцию.
- Транзакция начата после последней контрольной точки и завершилась до сбоя. Записи журнала вытолкнуты на диск. Изменения в блоках базы на диске не производились. Необходимо повторить все действия (накатить транзакцию).
- Транзакция начата после последней контрольной точки и не успела завершиться до сбоя. В журнале нет сведений о ней, изменения блоков базы были только в оперативной памяти. Делать ничего не нужно. Транзакция должна быть повторена.
6.5.5 Восстановление после жесткого сбоя
Для создания и пополнения архивных файлов устанавливают режим архивирования (archivelog). Если погибла часть жесткого диска или весь диск, то восстановление возможно только по данным архивных файлов и журнала транзакций. Желательно регулярно копировать файлы журналов на отдельные носители.
Порядок действий по восстановлению базы:
- По архивным файлам восстановить базу данных. Желательно иметь возможность восстановить базу по состоянию на предыдущий день.
- Если журнал сохранился, то по журналу повторяются все последние успешно завершившиеся транзакции. (При этом не нужно откатывать транзакции, прерванные в результате сбоя).
- Если журнал погиб, восстановление последних транзакций невозможно и база создается по состоянию на момент последней архивации.
Замечание. Комплекс работ по сохранению и восстановлению данных называется backup&recovery.
Хороший сервер это сложная система. В нем необходимо иметь источники питания и диски с горячей заменой. Источник бесперебойного питания рассчитывается так, чтобы он обеспечил работу во время запуска и выхода на режим дизель-генератора, обеспечивающего автономное питание практически на любое время. В серверном помещении должна быть создана эффективная система пожаротушения.
Должно быть организовано правильное архивирование данных. Журнал позволяет держать данные на сервере в течение небольшого времени, порядка часа. Необходимо наладить систему архивирования. Архив должен быть достаточно оперативным, т.е. если вы архивируете данные раз в месяц, то не исключено, что система погибнет перед очередным архивированием, и вы будете вынуждены вспоминать данные, которые вводились за последний месяц. Рекомендуется делать ежедневные архивы (администраторская "неделька"). Архивные носители желательно помещать в территориально удаленные хранилища.
В системах с правильной архивацией можно откатить базу на все время существования и восстановить ее практически при любых катастрофах. Теряются данные максимум за один последний день.