Chapter 62.通用 WAL 记录
尽管所有内置的 WAL 记录模块都有其自己的 WAL 记录类型,但是也存在通用的 WAL 记录类型,该类型以通用的方式描述页面的更改。这对于提供自定义访问方法的扩展很有用,因为它们无法注册自己的 WAL 重做例程。
用于构建通用 WAL 记录的 API 在access/generic_xlog.h
中定义,并在access/transam/generic_xlog.c
中实现。
要使用通用 WAL 记录工具执行 WAL 记录的数据更新,请按照下列步骤操作:
-
state = GenericXLogStart(relation)
—为给定的关系开始构建通用的 WAL 记录。 -
page = GenericXLogRegisterBuffer(state, buffer, flags)
—在当前通用 WALLogging 注册要修改的缓冲区。此函数返回一个指向缓冲区页面临时副本的指针,该副本应在此处进行修改。 (不要直接修改缓冲区的内容.)第三个参数是适用于该操作的标志的位掩码。当前,唯一这样的标志是GENERIC_XLOG_FULL_IMAGE
,它指示应该在 WALLogging 包括整页图像而不是增量更新。通常,如果页面是新页面或已被完全重写,则将设置此标志。如果 WAL 记录的操作需要修改多个页面,则可以重复GenericXLogRegisterBuffer
。 -
对上一步中获得的页面图像进行修改。
-
GenericXLogFinish(state)
—将更改应用于缓冲区并发出通用 WAL 记录。
可以通过调用GenericXLogAbort(state)
在上述任何步骤之间取消 WAL 记录的构造。这将放弃对页面图像副本的所有更改。
使用通用 WAL 记录工具时,请注意以下几点:
-
不允许直接修改缓冲区!所有修改都必须在从
GenericXLogRegisterBuffer()
获取的副本中进行。换句话说,进行通用 WAL 记录的代码永远不要自己调用BufferGetPage()
。但是,调用者仍然有责任在适当的时候锁定/解锁和锁定/解锁缓冲区。从GenericXLogRegisterBuffer()
之前到GenericXLogFinish()
之后,必须在每个目标缓冲区上保留排他锁。 -
缓冲区的注册(步骤 2)和页面图像的修改(步骤 3)可以自由混合,也就是说,两个步骤都可以按任意 Sequences 重复。请记住,缓冲区的注册 Sequences 应与重播期间获得锁的 Sequences 相同。
-
通用 WAL 记录可以注册的最大缓冲区数是
MAX_GENERIC_XLOG_PAGES
。如果超出此限制,将引发错误。 -
通用 WAL 假设要修改的页面具有标准布局,尤其是
pd_lower
和pd_upper
之间没有有用的数据。 -
由于您正在修改缓冲区页面的副本,因此
GenericXLogStart()
不会启动关键部分。因此,您可以安全地在GenericXLogStart()
和GenericXLogFinish()
之间进行内存分配,错误抛出等操作。唯一实际的关键部分位于GenericXLogFinish()
内部。也不必担心在错误退出期间调用GenericXLogAbort()
。 -
GenericXLogFinish()
负责将缓冲区标记为脏并设置其 LSN。您无需明确地执行此操作。 -
对于未记录的关系,除了没有发出实际的 WAL 记录外,其他所有操作均相同。因此,通常不需要对未记录的关系进行任何显式检查。
-
通用 WAL 重做功能将以与注册时相同的 Sequences 获取对缓冲区的排他锁。重做所有更改后,锁将以相同 Sequences 释放。
-
如果未为注册的缓冲区指定
GENERIC_XLOG_FULL_IMAGE
,则通用 WAL 记录将在新旧页面图像之间包含增量。此增量基于逐字节比较。对于在页面内移动数据的情况,这不是很紧凑,并且将来可能会得到改进。