Об алгоритмах и пользе инкрементальных контрольных точек в СУБД Oracle
Источник: Статья была предоставлена автором и опубликована в августовском номере 2005г. интернет-журнала "Oracle Magazine/Русское издание". Статья переопубликовывается по просьбе читателей, поскольку ее первоначальный текст недоступен.
ВведениеВ процессе изучения алгоритмов, используемых Oracle при выполнении инкрементальных контрольных точек, я был удивлен тем, что большинство администраторов баз данных если и понимают цели, для которых они используются, то с трудом себе представляют, что происходит при выполнении инкрементальных контрольных точек. Надо отметить, что и я до более детального изучения этого вопроса пребывал кое-где в заблуждении. Это и подтолкнуло к написанию небольшой статьи, в которой я попытался обобщить всю собранную из разных источников информацию, добавив к ней немного своих знаний и, по возможности, подтвердив это экспериментами. Вся информация в данной статье, если явно не указано другое, относится к версии Oracle 9.2.
Цели использования контрольных точек- Обеспечить физическую запись на диски часто обновляемых в буферном кэше блоков. Иначе эти блоки, расположенные в “горячей” части LRU-списка, могут длительное время не записываться на диски;
- обеспечить возможность циклического использования журнальных файлов;
- уменьшить время восстановления после сбоя экземпляра ( instance failure ) или носителя ( media failure ).
- Обеспечить сброс из буферного кэша на диски “грязных” буферов, переводимых в offline или в режим горячего резервирования файлов данных и табличных пространств.
Начиная с версии 8.0, в Oracle появилось понятие инкрементальных контрольных точек. Идея заключалась в том, чтобы “размазать” по времени часть работы, осуществляемой при выполнении нормальной (интервальной в терминах глоссария РДТЕХ) контрольной точки, уменьшить время восстановления после сбоя, сделать процессы DBWn более активными на сильно загруженных системах и системах с большим буферным кэшем. Кроме того, от инкрементальных контрольных точек требовалось как можно меньше негативно влиять на производительность системы в целом. Давайте сравним между собой алгоритмы прохождения нормальной и инкрементальной контрольных точек.
Нормальная контрольная точкаСобытия, при которых выполняется нормальная контрольная точка:
- при переключении оперативных журнальных групп ( log switch ) – до версии 8.1. Начиная с версии Oracle 8.1, переключение оперативных журнальных групп вызывает низкоприоритетную нормальную контрольную точку (подробнее - в Таблице 1);
- в Oracle версий до 8.1 при достижении экземпляром предельных значений, установленных параметрами инициализации LOG_CHECKPOINT_INTERVAL и LOG_CHECKPOINT_TIMEOUT. Начиная с версии 8.1, эти параметры влияют не на нормальную, а на инкрементальную контрольную точку;
- при выполнении команды ALTER SYSTEM CHECKPOINT;
- при выполнении команды SHUTDOWN NORMAL/ TRANSACTIONAL/IMMEDIATE;
- при восстановлении после сбоя экземпляра ( instance recovery ) или сбоя носителя ( media recovery ).
- при выполнении команд ALTER TABLESPACE XXX OFFLINE NORMAL/TEMPORARY, ALTER TABLESPACE XXX READ ONLY/BEGIN BACKUP;
- при выполнении команды ALTER DATABASE DATAFILE XXX OFFLINE;
Прохождение нормальной контрольной точки – это достаточно сложный и ресурсоемкий процесс, в который втянуты фоновые процессы DBWn (для простоты здесь и далее будем считать, что в системе сконфигурирован один такой процесс), LGWR и CKPT. Упрощенно это выглядит так:
- Определяется checkpoint SCN – номер системного изменения, на который будет согласована информация во всех структурах базы данных
- Процесс DBWR дает сигнал процессу LGWR записать в журнальные файлы всю информацию из log buffer , которая “защищает” изменения в блоках данных до checkpoint SCN включительно. DBWR ждет сигнала окончания записи от LGWR.
- DBWR записывает в файлы данных все “грязные” блоки, последние изменения которых были сделаны до checkpoint SCN включительно.
- После окончания записи DBWR дает сигнал CKPT обновить информацией о прошедшей контрольной точке заголовки всех online-файлов данных табличных пространств, находящихся в режиме read/write и следующие структуры в управляющем файле:
- FILE HEADER
- DATABASE ENTRY
- CHECKPOINT PROGRESS RECORD (для текущего номера THREAD)
- REDO THREAD RECORD (для текущего номера THREAD)
- DATA FILE RECORDS (для каждого файла данных, заголовок которого был обновлен информацией о прошедшей контрольной точке)
Как видим, при выполнении нормальной контрольной точки имеют место ожидания фоновых процессов друг друга, большой объем записи в файлы данных (пропорционально количеству “грязных” буферов в кэше, которое обычно пропорционально размеру буферного кэша) и управляющие файлы, а также запись в заголовки каждого файла данных, участвующего в процессе.
Нужно еще отметить, что существуют события (например , table drop/move/truncate, index drop/rebuild, direct read ), которые вызывают запись “грязных” блоков затрагиваемых операцией сегментов на диски и в этом смысле похожи на контрольные точки, но формально ими не являются, так как не осуществляют записи в управляющий файл и не сокращают время восстановления в случае сбоя.
Инкрементальная контрольная точкаС целью уменьшения негативного влияния контрольных точек на производительность системы, сокращения времени восстановления после сбоя, а также для обеспечения механизма heartbeat , в Oracle 8.0 был введен механизм инкрементальных контрольных точек.
Воспользовавшись рисунком 1, попытаемся разобраться в обсуждаемом механизме.
Рисунок 1
- В процессе выполнения команд DML и DDL серверные процессы копируют redo-информацию в log buffer .
- LGWR записывает информацию из log buffer в current online redo файлы. RBA (Redo Byte Address) последнего записанного блока называется on disk RBA .
- После окончания записи очередной порции информации из log buffer LGWR записывает RBA последнего записанного redo-блока в поле on disk RBA структуры, отражающей в оперативной памяти образ checkpoint progress record текущего thread. Эта структура отображается в виде таблицы x$kcccp.
- По мере того, как блоки данных в буферном кэше претерпевают изменения и становятся “грязными”, процесс DBWR формирует очередь ( checkpoint queue ) из связанных в упорядоченный по возрастанию low RBA список этих блоков. Low RBA – это redo-адрес первого изменения блока, сделавшего его “грязным”.
- В какой-то момент времени DBWR определяет, что один из параметров, управляющий наступлением инкрементальной контрольной точки, превысил свое пороговое значение. Начинается выполнение инкрементальной контрольной точки. DBWR вычисляет target RBA – то значение, до которого он будет осуществлять запись блоков из checkpoint queue . Этим значением не обязательно будет on disk RBA – то значение, до которого DBWR сможет безопасно записывать “грязные” буфера из буферного кэша, так как redo-информация, защищающая эти изменения, уже записана процессом LGWR в журнальные файлы. DBWR выберет в качестве target RBA значение, которое вернет после выполнения инкрементальной контрольной точки значение параметра, ее вызвавшее, в рамки допустимого.
- DBWR записывает все блоки из checkpoint queue от ее начала до target RBA включительно в файлы данных. При этом, в случае настройки асинхронного ввода-вывода, он может не ожидать завершения дисковых операций, а выполнять в это время другую работу – например, перемещать блоки в LRU-списках, даже осуществлять в случае необходимости запись “грязных” блоков из “холодной” части LRU-списка. То есть, выполнение инкрементальной контрольной точки является фоновой, низкоприоритетной для DBWR операцией. Это позволяет минимизировать нагрузку на экземпляр, и в этом одно из главных отличий инкрементальной контрольной точки от нормальной.
- По окончании записи всех “грязных” блоков до target RBA включительно процесс DBWR записывает адрес следующего за target RBA в checkpoint queue блока (или последнего блока из checkpoint queue , если оттуда были записаны все блоки) в качестве low cache RBA в x$kcccp – то есть, перемещает recovery-маркер.
- Процесс CKPT, активизирующийся каждые 3 секунды, увеличит на 1 счетчик heartbeat в x$kcccp и обновит checkpoint progress record текущего экземпляра в управляющем файле значением из x$kcccp. Таким образом, информация о прошедшей инкрементальной контрольной точке максимум через 3 секунды попадет в управляющий файл.
Таким образом, все, что происходит во время инкрементальной контрольной точки, – это запись процессом DBWR части “грязных” буферов из checkpoint queue на диски и минимальные манипуляции с этой очередью по ее окончанию.
Достоинства инкрементальных контрольных точекИтак, достоинства инкрементальных точек, а также их преимущества над нормальными заключаются в:
- Низком приоритете для DBWR связанных с ними операций ввода-вывода, что уменьшает нагрузку на систему. При большой нагрузке на подсистему ввода-вывода процесс DBWR дополняет пакеты блоков, предназначенных для записи, блоками из checkpoint queue.
- Инкрементальные контрольные точки ограничивают число “грязных” буферов в буферном кэше, что позволяет с большей долей вероятности удовлетворять потребности серверных процессов в свободных блоках и уменьшить ожидания free buffer waits .
- Инкрементальные контрольные точки могут существенно сократить время восстановления экземпляра после сбоя, в случае очень больших буферных кэшей – на порядки.
- В том, что упорядочивание блоков в checkpoint queue по возрастанию low RBA “грязных” блоков гарантирует, что более старые блоки будут записаны первыми. Это обеспечивает монотонное продвижение контрольной точки и позволяет полностью контролировать время восстановления экземпляра в случае сбоя.
- Инкрементальная контрольная точка не требует обновлений заголовков файлов данных и множества структур в управляющем файле путем выполнения дорогостоящих controlfile transactions . Производится только запись “грязных” блоков в файлы данных и “легковесная” запись в checkpoint progress record управляющего файла (и эта запись не использует механизм controlfile transactions и гораздо менее дорогостоящая. Для ее выполнения требуется лишь одна физическая операция записи).
- Во время прохождения инкрементальной контрольной точки, в отличие от обычной, процессы DBWn, LGWR и CKPT не ожидают друг друга.
- Использование инкрементальных точек в Oracle RAC позволяет уменьшить количество PI-буферов в буферных кэшах экземпляров, что уменьшает засорение такими блоками буферных кэшей.
- Механизм инкрементальных контрольных точек не конфликтует с механизмом commit cleanout . Дело в том, что после записи на диски “грязные” буфера не выбрасываются из буферного кэша, а только очищаются, то есть, становятся не “грязными”. Это дает возможность серверному процессу по окончании транзакции очистить блоки в быстром режиме.
- Слишком частое выполнение инкрементальных контрольных точек может негативно сказаться на производительности. Причиной может стать слишком малое значение одного из соответствующих параметров инициализации, слишком малый размер журнальных файлов, ошибки при вычислении пропускной способности дисковой подсистемы при выполнении восстановления после сбоя. Это может вызвать чрезмерную нагрузку на DBWR и систему ввода-вывода записью большого количества мелких порций блоков, что в свою очередь приведет к падению производительности. Кроме этого, в случае частого обновления одних и тех же блоков может сложиться ситуация, когда эти блоки будут постоянно перезаписываться, что приведет к дополнительной нагрузке на дисковую подсистему. То есть, может случиться так, что после очередной инкрементальной контрольной точки блок записывается на диск и очищается, но через небольшой промежуток времени снова становится “грязным” и цикл повторяется. Следует отметить, что в версиях Oracle до 8i, если серверный процесс пытается модифицировать блок данных, который находится в процессе записи на диск, то он будет находится в ожидании buffer busy waits до момента окончания записи этого блока. Начиная с версии 8i введена оптимизация, заключающаяся в том, что в подобном случае серверный процесс клонирует этот буфер, делает его текущим (current) и выполняет в нем требуемые изменения. После окончания записи старый current-блок конвертируется в cr-блок и может в дальнейшем использоваться механизмом версионности. Частоту этих операций можно посмотреть в статистиках write clones created in background и write clones created in foreground . Таким образом, хотя теперь подобные ситуации и практически исключают ожидания buffer busy waits , но приводят к повышенному потреблению ресурсов.
- При излишне частом выполнении инкрементальных контрольных точек возможно появление конкуренции за защелки checkpoint queue latch и active checkpoint queue latch .
- Разумеется, поддержка обсуждаемого механизма также требует небольших дополнительных ресурсов: места в оперативной памяти и ресурсов CPU для манипуляций с соответствующими структурами и защелками.
Как уже ранее говорилось, таблица x$kcccp является образом CHECKPOINT PROGRESS RECORD в оперативной памяти каждого экземпляра. По команде alter session set events 'immediate trace name controlf level 2' можно выдать в трассировочный файл информацию о содержимом управляющего файла и в том числе всех CHECKPOINT PROGRESS RECORDS:
Здесь среди прочего можно увидеть значение low RBA , начиная с которого, и значение on disk RBA , до которого будет производиться восстановление экземпляра после сбоя. Здесь же сохраняется периодически корректируемая во время восстановления экземпляра статистическая информация о производительности системы ввода-вывода.
По команде alter session set events 'immediate trace name buffers level 1' можно выдать в трассировочный файл содержимое заголовков всех блоков из буферного кэша:
Здесь в контексте обсуждаемой темы нас будут интересовать следующие поля:
- ckptq: [66fda2e8,66fda5d8] – адрес предыдущего и последующего блоков в checkpoint queue
- fileq: [66fda2f0,66fda5e0] – адрес предыдущего и последующего блоков в file checkpoint queue
- LRBA: [0x5ce.59e9.0] – low RBA блока
К сожалению, в x$bh из интересуемых нас полей можно увидеть только low RBA (x$bh.lrba_seq и x$bh.lrba_bno).
В некоторых версиях Oracle (в версии 8.1 и, возможно, в других) размер checkpoint queue в байтах можно увидеть в представлении V$SGASTAT (или его источнике x$ksmss).
Таблица 1. Параметры, имеющие отношение к инкрементальным контрольным точкам
Версия Oracle
- Инкрементальные контрольные точки не используются.
- Параметр инициализации LOG_CHECKPOINT_TO_ALERT влияет за запись информации о нормальных контрольных точках в alert.log.
- Параметры инициализации LOG_CHECKPOINT_INTERVAL и LOG_CHECKPOINT_TIMEOUT вызывают нормальную контрольную точку.
- Процесс CKPT является необязательным, его запуск контролируется параметром CHECKPOINT_PROCESS. В версиях 7.3.3 и 7.3.4 CKPT может запускаться автоматически при DB_FILES>50 или DB_BLOCK_BUFFERS>10000. Если процесс CKPT не запущен, его функции выполняет LGWR.
- Впервые вводятся инкрементальные контрольные точки.
- На их частоту влияет единственный параметр DB_BLOCK_MAX_DIRTY_TARGET.
- Процесс CKPT становится обязательным и запускается автоматически.
- Checkpoint queue отсутствует, поэтому инкрементальные контрольные точки записывают “грязные” блоки не упорядочено по времени их первого обновления. Это не может полностью гарантировать уменьшение времени восстановления, т.к. не гарантирует первоочередную запись самых старых буферов.
- Появляется структура памяти, называемая checkpoint queue . Блоки данных в ней упорядочены по их low RBA , что позволяет записывать самые старые блоки в первую очередь и монотонно продвигать в redo (и, соответственно, по времени) контрольную точку.
- При переключении оперативных журналов теперь происходит растянутая по времени нормальная контрольная точка, которая не приводит к пиковой нагрузке на экземпляр, но повышает требования к количеству и размеру журнальных файлов. При переключении журналов начинается нормальная контрольная точка, имеющая “нулевой приоритет”: она будет закончена тогда, когда очередная инкрементальная точка переведет low RBA из предыдущего ( active ) в текущий ( current ) журнальный файл.
- Параметры инициализации LOG_CHECKPOINT_INTERVAL и LOG_CHECKPOINT_TIMEOUT получают новый смысл – теперь они вызывают инкрементальную контрольную точку.
- Инкрементальную контрольную точку вызывает достижение параметра LOG_CHECKPOINT_INTERVAL значения 90% от размера наименьшего журнального файла.
- В версии Oracle 8i Enterprise Edition появляется новый параметр FAST_START_IO_TARGET
- Введен новый параметр инициализации FAST_START_MTTR_TARGET
- Если параметр FAST_START_MTTR_TARGET не установлен, Oracle использует самонастраиваемый алгоритм, который осуществляет инкрементальные контрольные точки в период наименьшей активности подсистемы ввода-вывода.
Из всего вышесказанного можно сделать вывод, что механизм инкрементальных контрольных точек имеет гораздо больше достоинств, чем недостатков. Кроме уменьшения времени восстановления после сбоев в большинстве случаев он позволяет также и увеличить производительность системы. Все возможные негативные влияния механизма инкрементальных контрольных точек связаны с их излишней, чрезмерной частотой. Особенно сильно это может негативно сказаться на производительности сильно загруженных операциями ввода-вывода систем. Поэтому администраторы таких баз данных должны найти компромисс между снижением времени восстановления после сбоев и вызываемой механизмом инкрементальных точек повышенной нагрузкой на подсистему ввода-вывода, операционную систему, на структуры памяти и процессы СУБД Oracle, участвующие в поддержке этого механизма.
В заключении хочется поблагодарить сотрудника отдела технической поддержки компании РДТЕХ Андрея Криушина за полезные замечания и поддержку при написании данной статьи.