Глава 62. Общие записи WAL#

Глава 62. Общие записи WAL

Глава 62. Общие записи WAL

Хотя все встроенные модули, записывающие WAL, имеют свои собственные типы записей WAL, также существует общий тип записи WAL, который описывает изменения страниц общим способом. Это полезно для расширений, предоставляющих пользовательские методы доступа.

В сравнении с Пользовательскими менеджерами ресурсов WAL, Общий WAL проще для реализации расширения и не требует загрузки библиотеки расширения для применения записей.

Примечание

Общие записи WAL игнорируются во время Логического декодирования. Если для вашего расширения требуется логическое декодирование, рассмотрите возможность использования пользовательского менеджера ресурсов WAL.

API для создания общих записей WAL определено в файле access/generic_xlog.h и реализовано в файле access/transam/generic_xlog.c.

Для выполнения обновления данных с записью WAL с использованием общего механизма записи WAL следуйте этим шагам:

  1. state = GenericXLogStart(relation) — начинает построение общего WAL-записи для указанного отношения.

  2. page = GenericXLogRegisterBuffer(state, buffer, flags) — регистрирует буфер для изменения в текущей общей записи WAL. Эта функция возвращает указатель на временную копию страницы буфера, где следует вносить изменения. (Не изменяйте содержимое буфера напрямую). Третий аргумент - это битовая маска флагов, применимых к операции. В настоящее время единственным таким флагом является GENERIC_XLOG_FULL_IMAGE, который указывает, что в записи WAL должно быть включено полностраничное изображение, а не дельта-обновление. Обычно этот флаг устанавливается, если страница является новой или была полностью перезаписана. GenericXLogRegisterBuffer может повторяться, если запись в WAL требует изменения нескольких страниц.

  3. Примените изменения к изображениям страниц, полученным на предыдущем шаге.

  4. GenericXLogFinish(state) — применить изменения к буферам и записать общую запись WAL.

WAL-запись может быть отменена между любыми из вышеуказанных шагов путем вызова функции GenericXLogAbort(state). Это приведет к отмене всех изменений в копиях изображений страницы.

Пожалуйста, обратите внимание на следующие моменты при использовании общего механизма записи WAL:

  • Прямые изменения буферов запрещены! Все изменения должны выполняться в копиях, полученных из функции GenericXLogRegisterBuffer(). Другими словами, код, создающий общие записи WAL, никогда не должен вызывать функцию BufferGetPage() для себя. Однако, вызывающая сторона должна самостоятельно закреплять/откреплять и блокировать/разблокировать буферы в нужное время. Исключающая блокировка должна быть установлена на каждом целевом буфере с момента перед вызовом функции GenericXLogRegisterBuffer() до момента после вызова функции GenericXLogFinish().

  • Регистрация буферов (шаг 2) и модификации изображений страниц (шаг 3) могут быть свободно смешаны, то есть оба шага могут быть повторены в любой последовательности. Имейте в виду, что буферы должны быть зарегистрированы в том же порядке, в котором на них будут получены блокировки во время повторного воспроизведения.

  • Максимальное количество буферов, которые могут быть зарегистрированы для общей записи WAL, составляет MAX_GENERIC_XLOG_PAGES. Если это ограничение будет превышено, будет сгенерирована ошибка.

  • В общем случае, Generic WAL предполагает, что страницы, которые будут изменены, имеют стандартную структуру, и в частности, что между pd_lower и pd_upper нет полезных данных.

  • Поскольку вы изменяете копии буферных страниц, GenericXLogStart() не запускает критическую секцию. Таким образом, вы можете безопасно выполнять выделение памяти, генерацию ошибок и т. д. между GenericXLogStart() и GenericXLogFinish(). Единственная фактическая критическая секция находится внутри GenericXLogFinish(). Нет необходимости беспокоиться о вызове GenericXLogAbort() при ошибке выхода.

  • GenericXLogFinish() заботится о пометке буферов как грязных и установке их LSN. Вам не нужно делать это явно.

  • Для незафиксированных отношений все работает так же, за исключением того, что не создается фактическая запись WAL. Таким образом, обычно вам не нужно выполнять явные проверки для незафиксированных отношений.

  • Функция обобщенного восстановления журнала транзакций (WAL) будет получать исключающие блокировки на буферах в том же порядке, в котором они были зарегистрированы. После восстановления всех изменений блокировки будут освобождены в том же порядке.

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