2024 年 9 月 26 日:PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持的版本: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的目的是确保在更改数据库记录之前写入日志,但这可能会被错误地向内核报告成功写入的磁盘驱动器 破坏,而实际上它们只是缓存了数据,尚未将其存储在磁盘上。在这种情况下发生电源故障可能会导致数据损坏无法恢复。管理员应尝试确保保存 PostgreSQLWAL文件的磁盘不会发出此类错误报告。(请参阅第 28.1 节。)

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

为了处理 pg_control 损坏的情况,我们应该支持以相反的顺序(从最新到最旧)扫描现有 WAL 段的可能性,以便找到最新的检查点。这还没有实现。 pg_control 足够小(小于一个磁盘页面),因此它不会受到部分写入问题的影响,并且在撰写本文时,还没有关于数据库故障的报告仅仅是由于无法读取 pg_control 本身。因此,虽然理论上它是一个弱点,但 pg_control 在实践中似乎不是问题。

提交更正

如果您在文档中发现任何不正确的地方,与您对特定功能的体验不符或需要进一步说明,请使用此表单报告文档问题。