支持的版本:Current (17) / 16 / 15 / 14 / 13
开发版本:devel
不受支持的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4

28.6. WAL 内部结构 #

WAL会自动启用;不需要管理员采取任何操作(除了确保满足WAL文件的磁盘空间需求,并且已执行任何必要的调整(参见 章节 28.5)。

WAL记录追加到WAL文件中,因为每写一条新记录会记录一条新记录。插入位置由日志序列号 (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 的磁盘WAL文件不做出此类错误的报告。(参见 章节 28.1。)

在完成检查点并刷新 WAL 后,检查点的位置会保存在 pg_control 文件中。因此,在恢复开始时,服务器首先读取 pg_control 以及检查点记录;然后从检查点记录中指示的 WAL 位置向前扫描,执行 REDO 操作。因为在检查点之后的数据页面的整个内容保存在 WAL 中,它是对第一个页面修改之后的内容保存的(假设未禁用 full_page_writes),所以在检查点后发生更改的所有页面都将恢复为一致的状态。

为了处理 pg_control 已损坏的情况,我们应该支持按相反的顺序(从最新到最旧)扫描现有 WAL 段的可能性,以便找到最新的检查点。该操作尚未实施。 pg_control 非常小(小于一页),以至于不会出现部分写入问题,并且在撰写本文时,还没有出现仅因无法读取 pg_control 本身而导致数据库故障的情况。所以,尽管从理论上这是一个弱点,但实际上 pg_control 似乎没有问题。

提交更正

如果你在文档中发现不正确的问题,或者与你有关特定功能的体验不一致,或需要进一步的说明,请使用 此表单 报告文档问题。