среда, 2 января 2013 г.

29.4. Настройка WAL

Есть несколько связанных с WAL параметров конфигурации, которые влияют на производительность БД. Этот раздел объясняет как их использовать. По поводу настройки сервера обращайтесь к главе 18.
Checkpoints - это точки в последовательности транзакций в которых гарантируется, что файлы данных heap и index содержат всю информацию, записанную до этой точки. На момент чекпойнта все страницы грязных данных записаны на диск и в лог-файл записана специальная запись чекпойнта. (Изменения перед этим записаны в WAL файлы). Если происходит падение, то процесс восстановления смотрит на последний чекпойнт, чтобы определить место в логах (известное как redo record), откуда должна быть начата операция REDO. Все изменения, сделанные до этого момента гарантированно записаны на диск. По этой причине все сегменты, расположенные до чекпойнта могут быть удалены или перезаписаны. (Когда происходит архивирование WAL - сегменты лога должны быть заархивированы до того, как они будут удалены или перезаписаны.)
Необходимость того, что все страницы грязных данных до создания чекпойнта должны быть записаны на диск может создать значительную I/O нагрузку. По этой причине эта нагрузка растягивается до начала следующего чекпойнта, что снижает влияние на производительность.
Фоновый процесс записи автоматически создаёт чекпойнты. Чекпойнт создаётся каждый checkpoint_segments сегмент логов или каждую checkpoint_timeout секунду, смотря что раньше. Значения по умолчанию - 3 сегмента и 300 секунд (5 минут). Кроме того, создать чекпойнт можно при помощи SQL команды CHECKPOINT.
Сокращение checkpoint_segments и / или checkpoint_timeout увеличивает частоту создания чекпойнтов. Такой подход позволяет ускорить восстановление после краха (так как меньше работы придётся делать); с другой же стороны это увеличивает нагрузку на диск. Если установлен full_page_writes (как и есть по умолчанию), то появляется ещё один фактор, который надо учитывать. В таком случае, чтобы быть уверенным в последовательности страниц данных, первое изменение страницы данных после каждого чекпойнта отражается в логе записью всей страницы. Теперь небольшой интервал между чекпойтами увеличивает объём WAL логов, частично снижая цель установки небольшого интервала, и, в любом случае, повышает нагрузку на диск.
Чекпойты относительно дороги. Во-первых, потому что они требуют записи всех текущих грязных буферов; а во-вторых, потому что они увеличивают WAL трафик, как говорилось выше. Таким образом лучше всего установить параметры чекпойнта достаточно большими, чтобы они происходили не так часто. Здравым способом проверить ваши параметры чекпойнтов является установка параметра checkpoint_warning. Если чекпойнты создаются чаще, чем checkpoint_warning секунд, сообщение в логах сервера порекомендует увеличить checkpoint_segments. Редкое появление таких сообщений не повод для тревоги, однако при их частом появлении следует увеличить параметры чекпойнтов. Объёмные операции, такие как объёмное копирование, могут увеличить число таких сообщений, если значение checkpoint_segments недостаточно высоко.
Чтобы избежать перегрузки системы ввода / вывода, запись грязных буферов при создании чекпойнта распределена во времени. Время, выделенное на эту запись контролируется параметром checkpoint_completion_target, который задаёт часть интервала чекпойнта. Интенсивность записи подгоняется таким образом, чтобы чекпойнт был записан по достижении указанной части WAL сегментов, созданных между чекпойнтами, или секунд между ними, смотря что быстрее. При значении по умолчанию в 0.5 PostgreSQL будет завершать запись каждого чекпойнта за половину времени до создания нового чекпойнта. На системах с большой нагрузкой на систему ввода/вывода имеет смысл увеличить значение checkpoint_completion_targt для снижения нагрузки от создания чекпойнтов. Обратная сторона такого решения заключается в том, что это увеличит время восстановления, так как придётся хранить больше WAL сегментов. Хотя checkpoint_completion_target может иметь значение и больше 1, всё же лучше бы оно было меньше 1 (например, 0.9), так как создание чекпойнта включает ещё некоторую деятельность, кроме записи грязных буферов. Если же значение checkpoint_completion_target будет 1.0, то практически наверняка создание чекпойнта не будет завершено вовремя, что приведёт к падению производительности из-за неожиданного изменения числа необходимых WAL сегментов.
Всегда должен быть как минимум один файл WAL сегмента, и их обычно не больше чем (2 + checkpoint_completion_target) * checkpoint_segments + 1 или checkpoint_segments + wal_keep_segments + 1 файл. Каждый файл сегмента обычно занимает 16Мб (хотя это значение может быть изменено при компиляции сервера). Используя это значение Вы можете подсчитать объём, необходимый для хранения WAL. Обычно, когда старые лог-файлы уже не нужны, они перезаписываются (и переименовываются, чтобы соответствовать новому номеру сегмента). Если (по причине всплеска создания лог-файлов) у Вас больше чем 3 * checkpoint_segments + 1 файл, то ненужные файлы будут просто удалены, чтобы не превышать установленный лимит.
В archive recovery или standby сервер периодически выполняет restartpoints (т.е. практически отметка, что чекпойнт был восстановлен), что похоже на checkpoint в обычном режиме: сервер сохраняет всё свое состояние на диск, обновляет pg_control файл, чтобы сообщить, что уже обработанные WAL данные не требуют повторной обработки, после чего рециркулируются все старые лог-файлы в каталоге pg_xlog. restartpoint срабатывает, если как минимум один чекпойнт был восстановлен и прошло checkpoint_timeout секунд с последнего restartpoint. В standby режиме restartpoint так же срабатывает если checkpoint_segments сегментов было восстановлено с последней restartpoint и был восстановлен хоть один чекпойнт. Restartpoint не может быть чаще, чем чекпойнты на мастере, так как restartpoint могут быть выполнены только для записей чекпойнтов.
Есть две часто используемые внутренние WAL функции: LogInsert и LogFlush. LogInsert используется для помещения новой записи в WAL буфер в общей памяти. Если там нет места для новой записи, LogInsert будет должен записать (переместив в кеш ядра) несколько заполненных WAL буферов. Это нежелательно, так как LogInsert используется для низкоуровневых модификаций БД (например, вставки строк) когда на нужных страницах памяти установлена эксклюзивная блокировка, так что эта операция должна быть проведена быстро. Что ещё хуже, запись WAL буферов может так же привести к созданию нового сегмента лога, что занимает ещё больше времени. Обычно WAL буферы должны быть записаны и скинуты на диск по запросу LogFlush, который обычно вызывается при завершении транзакции, чтобы убедиться, что записи транзакции сохранены в постоянное хранилище. На системах с большим количеством логов запросы LogFlush могут возникать не так часто, чтобы предотвратить создание записей LogInsert. На таких системах необходимо увеличить число WAL буферов, изменив параметр конфигурации wal_buffers. Значение по умолчанию - 8. Увеличение этого параметра приведёт к увеличению использования общей памяти. Если full_page_writes установлен и система очень занята, то увеличение этого параметра поможет сгладить время отклика в период непосредственно после каждой контрольной точки.
Параметр commit_delay определяет сколько микросекунд серверный процесс должен сделать паузу после записи подтверждения в лог при помощи LogInsert до выполнения LogFlush. Эта пауза позволяет другим серверным процесса добавить свои записи подтверждения в лог, чтобы потом все их вместе выгрузить на диск. Работа без паузы может возникнуть при отключённом fsync или если в активной транзакции меньше чем commit_siblings других сессий; в таком случае маловероятно что другие сессии сделают в ближайшее время подтверждение. Обратите внимание, что на большинстве платформ время паузы детализируется с точностью до миллисекунд, так что любое ненулевое значение commit_delay между 1 и 10000 (1000 наверно - прим. переводчика) микросекунд будет иметь один и тот же эффект. Хорошее значение этого параметра до сих пор не известно, так что экспериментируйте.
Параметр wal_sync_method определяет как PostgreSQL будет просить ядро записать обновления WAL на диск. Все параметры должны быть одинаковы с точки зрения надежности, за исключением fsync_writethrough, который иногда может принудительно писать на диск из кеша, даже если другие опции не указывают на это. Тем не менее в достаточной степени зависит от платформы то, какая из опций будет быстрее; проверить их скорости можно при помощи модуля pg_test_fsync модуля. Обратите внимание, что этот параметр не обращает внимание на iffsync.
Включение параметра конфигурации wal_debug (доступен в PostgreSQL, который был скомпилирован с поддержкой этого) приведёт к тому, что каждый вызов LogInsert и LogFlush будет занесён в лог. Эта опция может быть в поздних версиях заменена на более общий механизм.

Комментариев нет:

Отправить комментарий