目录标题
PostgreSQL 归档失败 & WAL 堆积原因分析(基于 pgBackRest)
1. 背景
集群采用 pgBackRest 作为备份与归档管理工具,所有 Base Backup 与 WAL 文件统一存储在 NFS 目录中,由 pgBackRest 负责维护 仓库(repository) 的完整性与元数据。
2. 正常归档流程(pgBackRest)
-
PostgreSQL 在 WAL 切换时执行
archive_command,调用pgbackrest archive-push。 -
pgbackrest archive-push会:- 检查仓库元数据是否一致(
archive.info、backup.info等)。 - 将 WAL 复制到 NFS 仓库下的
archive/<cluster-name>/...。 - 更新归档索引,确认该 WAL 已归档。
- 检查仓库元数据是否一致(
-
命令返回 0 → PostgreSQL 判定归档成功,可以清理旧 WAL。
3. 删除 NFS 文件的影响
手工删除 NFS 上的备份或 WAL 文件,不仅仅是“文件丢了”,而是 破坏了 pgBackRest 仓库的完整性:
-
元数据损坏
-
pgBackRest 的仓库中有两个关键元数据文件:
backup.info:记录所有 Base Backup 集的起止 LSN、依赖关系。archive.info:记录归档的 WAL 序列及起始位置。
-
当 NFS 中的历史 WAL 或 Base Backup 被直接删除后,
backup.info/archive.info与实际文件内容对不上,仓库立即被判定为“损坏”。
-
-
归档失败
pgbackrest archive-push在写入新 WAL 前,会强制校验仓库一致性。- 一旦发现元数据不完整(缺 WAL 或缺 Base Backup),就直接报错退出,返回非 0。
- PostgreSQL 接收到非 0 → 认定归档失败。
-
WAL 堆积
- 因为 PostgreSQL 没有确认 WAL 被归档成功,它不会清理 pg_wal 中的旧 WAL。
- 从 14 号起,所有 WAL 一直无法清理,磁盘空间迅速上涨,导致 WAL 堆积。
4. 为什么“删历史文件”影响“新归档”
这是因为:
- pgBackRest 并不是简单复制文件,而是 管理整个仓库的一致性。
- 新归档的 WAL 需要被记录在
archive.info里,但如果前序 WAL/Backup 集缺失,仓库状态就不合法。 - 所以 删历史文件 = 破坏仓库元数据 = 新归档直接失败。
- 正确做法:只能用
pgbackrest expire命令删除过期文件,而不是rm。
5. 根因总结
NFS 上的备份/WAL 文件被手工删除 → pgBackRest 仓库元数据与实际文件不一致 → pgBackRest 主动判定归档失败 → PostgreSQL 无法清理 WAL → pg_wal 持续膨胀。
6. 解决方案
-
重建仓库
- 暂停归档,清理损坏仓库。
- 重新执行一次
pgbackrest backup生成新的 Base Backup。 - 重新启用
archive-push。
-
管理规范
- 禁止直接操作 NFS 文件。
- 使用
pgbackrest expire管理过期备份与 WAL。 - 监控
pgbackrest check、archive-push日志,避免归档失败长时间未发现。
✅ 对外说明可以简化为一句话:
由于手工删除了 NFS 上的历史备份文件,导致 pgBackRest 仓库元数据损坏,从而使归档判定失败,引起 PostgreSQL WAL 无法清理并持续堆积。
要不要我帮你画一个 pgBackRest + PostgreSQL 归档流程图(含失败路径),方便在复盘会上展示?
318

被折叠的 条评论
为什么被折叠?



