背景
PG 实例主备切换后,归档的时候,都是按照 0009、0010、…、0070(WAL 文件的尾号)顺序归档日志,但是归档完 0070 后,突然开始归档 0008 (正好是主备切换的 WAL),然后继续顺着 0071、0072 归档。
- 版本:PG 12
原理介绍
PG 归档的大致原理分为以下几步:
- 生成 0001 WAL 文件;
- WAL 满/WAL 切换/CHECKPOINT 判定 0001 对应的 WAL 文件需要被归档;
- 生成 0001.ready 文件,并通知 archiver 进程,可以归档此 WAL;
- archiver 归档该 WAL,将 0001.ready 改名为 0001.done;
- checkpointer 进程发现 0001.done 文件已存在,判定 0001 WAL 已经归档完成,可以删除;
问题分析
实例的新主在 promote 完成时对应的 WAL 为 0008,而下一个日志是从 0009 开始写,所以后续的归档先从 0009 开始。
等到了某一个 checkpoint 时(取决于 wal_keep_segment/max_wal_size/slot 等信息),通过 KeepLogSeg
函数计算,所有早于 某个 segno 的WAL 都需要被移除掉。而 0008 此时也小于该 segno,可以被移除掉。
Checkpointer 进程会通过 XLogArchiveCheckDone 函数检查该 WAL 是否可以被移除:由于并没有检查到 0008.done 文件(之前没有生成过 0008.ready,自然也没有 done 文件),所以此时 checkpointer 进程会生成一个 0008.ready 文件。
这时候,archiver 进程发现 0008.ready 文件生成,就会去将其归档。因此就出现了再按照顺序归档到 0070 后,中间插了一个 0008,接着继续顺着 0071 归档。
等 0008.done 生成后,到了再下一次 checkpoint,checkpointer 进程发现此时已经有了 0008.done 文件,可以该 WAL 文件删除。