Общие записи WAL

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

API для построения универсальных записей WAL определяется в access/generic_xlog.h.

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

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

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

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

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

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

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

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

  • Регистрация буферов (Шаг 2) и модификация изображений страниц (Шаг

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

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

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

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

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

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

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