WAL 会自动启用;管理员无需执行任何操作,只需确保满足 WAL 文件的磁盘空间要求,并完成任何必要的调整(请参阅第 30.5 节)。
随着每条新记录的写入,WAL 记录会追加到 WAL 文件。插入位置由日志序列号 (LSN) 描述,LSN 是 WAL 中的字节偏移量,随着每条新记录的增加而单调递增。LSN 值作为数据类型 pg_lsn
返回。可以比较值以计算将它们分开的 WAL 数据的量,因此它们用于衡量复制和恢复的进度。
WAL 文件存储在数据目录下的 pg_wal
目录中,作为一系列段文件,每个文件通常大小为 16 MB(但可以通过更改 --wal-segsize
initdb 选项来更改大小)。每个段都分为若干页,每页通常为 8 kB(可以通过 --with-wal-blocksize
配置选项来更改此大小)。WAL 记录头在 access/xlogrecord.h
中进行描述;记录内容取决于正在记录的事件类型。段文件被赋予不断增加的数字作为名称,从 000000010000000000000001
开始。这些数字不会环绕,但要耗尽可用的数字库存需要很长很长的时间。
如果 WAL 位于与主数据库文件不同的磁盘上,则很有利。可以通过将 pg_wal
目录移动到另一个位置(当然,在服务器关闭时)并在主数据目录中的原始位置和新位置之间创建一个符号链接来实现这一点。
WAL 的目的是确保在更改数据库记录之前写入日志,但这可能会被错误地向内核报告成功写入的磁盘驱动器破坏,而实际上它们只缓存了数据,尚未将其存储在磁盘上。在这种情况下,电源故障可能会导致不可恢复的数据损坏。管理员应尝试确保保存 PostgreSQL's WAL 文件的磁盘不会发出此类错误报告。(请参阅 第 30.1 节。)
在检查点创建并刷新 WAL 之后,检查点的位置将保存在文件 pg_control
中。因此,在恢复开始时,服务器首先读取 pg_control
,然后读取检查点记录;然后,它通过从检查点记录中指示的 WAL 位置向前扫描来执行重做操作。由于在检查点之后对数据页的首次页面修改时,数据页的全部内容都保存在 WAL 中(假设未禁用 full_page_writes),因此自检查点以来更改的所有页都将恢复到一致状态。
为了处理 pg_control
损坏的情况,我们应该支持按相反顺序(从最新到最旧)扫描现有 WAL 段的可能性,以便找到最新的检查点。此功能尚未实现。 pg_control
足够小(小于一个磁盘页),因此不受部分写入问题的影响,并且截至目前为止,尚未有因无法读取 pg_control
本身而导致的数据库故障报告。因此,虽然从理论上来说这是一个弱点,但 pg_control
在实践中似乎并不是一个问题。