Общие записи WAL#
Хотя все встроенные модули с WAL-записями имеют свои собственные типы WAL-записей, существует также общий тип WAL-записи, который описывает изменения страниц в общем виде. Это полезно для модулей, предоставляющих пользовательские методы доступа.
По сравнению с пользовательскими менеджерами ресурсов WAL, общий тип WAL-записи проще для реализации расширением и не требует загрузки библиотеки расширения для применения записей.
Примечание:
Общие записи WAL игнорируются во время логического декодирования. Если для вашего расширения требуется логическое декодирование, обратите внимание на пользовательский диспетчер ресурсов WAL.
API для создания общих записей WAL определен в файле access/generic_xlog.h и реализован в файле access/transam/generic_xlog.c.
Чтобы выполнить обновление данных в журнале WAL с помощью общего средства записи WAL, выполните следующие действия:
state = GenericXLogStart(relation)- начните построение общей записи WAL для данного отношения.page = GenericXLogRegisterBuffer(state, buffer, flags)- зарегистрируйте буфер для модификации в текущей общей записи WAL. Эта функция возвращает указатель на временную копию страницы буфера, в которой должны быть произведены изменения. (Не изменяйте содержимое буфера напрямую). Третий аргумент - битовая маска флагов, применимых к данной операции. В настоящее время единственным таким флагом являетсяGENERIC_XLOG_FULL_IMAGE, который указывает, что в запись WAL должен быть включен образ всей страницы, а не дельта-обновление. Обычно этот флаг устанавливается, если страница новая или была полностью переписана.GenericXLogRegisterBufferможет быть повторен, если действие, занесенное в WAL-журнал, должно изменить несколько страниц.Внесите изменения в изображения страниц, полученные в предыдущем шаге.
GenericXLogFinish(state)- примените изменения к буферам и создайте общую запись WAL.
Построение записи WAL можно отменить между любыми из вышеперечисленных этапов, вызвав GenericXLogAbort(state). При этом все изменения в копиях изображений страниц будут отменены.
Обратите внимание на следующие моменты при использовании общих записей WAL:
Прямые модификации буферов запрещены! Все модификации должны выполняться в копиях, получаемых из
GenericXLogRegisterBuffer(). Другими словами, код, создающий общие записи WAL, никогда не должен вызыватьBufferGetPage()для себя. Тем не менее, вызывающая сторона по-прежнему несет ответственность за подключение/отключение и блокировку/разблокировку буферов в соответствующие моменты времени. Исключительная блокировка должна удерживаться на каждом целевом буфере с момента вызоваGenericXLogRegisterBuffer()до завершенияGenericXLogFinish().Регистрацию буферов (шаг 2) и модификацию изображений страниц (шаг 3) можно смешивать, т.е. повторять оба шага в любой последовательности. Следует помнить, что буферы должны быть зарегистрированы в том же порядке, в котором будут получены блокировки на них при воспроизведении.
Максимальное количество буферов, которое может быть зарегистрировано для общей записи WAL, равно
MAX_GENERIC_XLOG_PAGES. При превышении этого лимита будет выдана ошибка.Общий тип WAL предполагает, что изменяемые страницы имеют стандартный макет, и в частности, что между
pd_lowerиpd_upperнет никаких полезных данных.Поскольку изменяются копии страниц буфера,
GenericXLogStart()не запускает критически важную секцию. Таким образом, междуGenericXLogStart()иGenericXLogFinish()можно спокойно выполнять выделение памяти, отбрасывание ошибок и т.д. Единственная реальная критическая секция находится внутриGenericXLogFinish(). Также нет необходимости беспокоиться о вызовеGenericXLogAbort()во время выхода из ошибки.GenericXLogFinish()позаботится о том, чтобы пометить буферы грязными и установить их LSN. Не нужно делать это явно.Для незарегистрированных отношений все работает так же, за исключением того, что не выдается фактическая запись WAL. Таким образом, обычно не нужно делать никаких явных проверок для незарегистрированных отношений.
Общая функция WAL redo приобретает эксклюзивные блокировки буферов в том же порядке, в котором они были зарегистрированы. После повторного выполнения всех изменений блокировки будут освобождены в том же порядке.
Если
GENERIC_XLOG_FULL_IMAGEне указан для зарегистрированного буфера, общая запись WAL содержит дельту между старым и новым образами страниц. Эта дельта основана на сравнении байт за байтом. Это не очень компактно для случая перемещения данных внутри страницы и может быть улучшено в будущем.