Skip to content

30.6. WAL 内部#

WAL会自动启用;管理员无需执行任何操作,只需确保满足WAL文件的磁盘空间要求,并完成任何必要的调整(请参阅第 30.5 节)。

随着每条新记录的写入,WAL记录会追加到WAL文件。插入位置由日志序列号 (LSN) 描述,LSN是 WAL 中的字节偏移量,随着每条新记录的增加而单调递增。LSN值作为数据类型pg_lsn返回。可以比较值以计算将它们分开的WAL数据的量,因此它们用于衡量复制和恢复的进度。

WAL文件存储在数据目录下的pg_wal目录中,作为一系列段文件,每个文件通常大小为 16 MB(但可以通过更改--wal-segsizeinitdb选项来更改大小)。每个段都分为若干页,每页通常为 8 kB(可以通过--with-wal-blocksize配置选项来更改此大小)。WAL 记录头在access/xlogrecord.h中进行描述;记录内容取决于正在记录的事件类型。段文件被赋予不断增加的数字作为名称,从000000010000000000000001开始。这些数字不会环绕,但要耗尽可用的数字库存需要很长很长的时间。

如果 WAL 位于与主数据库文件不同的磁盘上,则很有利。可以通过将pg_wal目录移动到另一个位置(当然,在服务器关闭时)并在主数据目录中的原始位置和新位置之间创建一个符号链接来实现这一点。

WAL的目的是确保在更改数据库记录之前写入日志,但这可能会被错误地向内核报告成功写入的磁盘驱动器破坏,而实际上它们只缓存了数据,尚未将其存储在磁盘上。在这种情况下,电源故障可能会导致不可恢复的数据损坏。管理员应尝试确保保存PostgreSQL'sWAL文件的磁盘不会发出此类错误报告。(请参阅第 30.1 节。)

在检查点创建并刷新 WAL 之后,检查点的位置将保存在文件pg_control中。因此,在恢复开始时,服务器首先读取pg_control,然后读取检查点记录;然后,它通过从检查点记录中指示的 WAL 位置向前扫描来执行重做操作。由于在检查点之后对数据页的首次页面修改时,数据页的全部内容都保存在 WAL 中(假设未禁用full_page_writes),因此自检查点以来更改的所有页都将恢复到一致状态。

为了处理pg_control损坏的情况,我们应该支持按相反顺序(从最新到最旧)扫描现有 WAL 段的可能性,以便找到最新的检查点。此功能尚未实现。pg_control足够小(小于一个磁盘页),因此不受部分写入问题的影响,并且截至目前为止,尚未有因无法读取pg_control本身而导致的数据库故障报告。因此,虽然从理论上来说这是一个弱点,但pg_control在实践中似乎并不是一个问题。