暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

PostgreSQL 12.4数据库“孤儿”归档问题处理的经验总结

原创 subverter 2026-01-22
218

1. 基本情况

在一次对某业务系统的PostgreSQL 12.4数据库进行常规维护后,监控系统发出告警,显示主库的WAL(预写式日志)归档目录 /archive 磁盘使用率持续快速增长,远超日常水平。经初步查看,发现该目录下积压了大量已生成的*.ready标记文件,但对应的WAL日志文件(如0000000100001234000000A9)并未被归档脚本成功转移至远程备份存储。

数据库本身运行正常,业务未受影响。但此情况若持续,将导致归档目录所在磁盘被写满,进而可能触发数据库因无法继续归档而挂起(如果archive_command失败且archive_mode为on),对系统高可用性和数据安全性构成严重威胁。此问题即典型的“孤儿”归档问题——WAL日志文件已生成并标记为就绪,但归档流程未完成或失败,留下“孤儿”状态的*.ready文件。

2. 问题定位

我们立即组建了处理小组,按照以下步骤进行问题定位

(1)检查归档状态与配置:

执行 SELECT * FROM pg_stat_archiver;。关键发现:last_failed_wal和last_failed_time字段有持续记录,且failed_count在增长。last_archived_wal的LSN位置远落后于last_archived_time,表明归档确实长时间未成功。

检查postgresql.conf中相关配置:

ini archive\_mode = on archive\_command = 'cp %p /archive/%f && rm /archive/%f\*.ready && touch /archive/%f.done'

配置本身无语法错误。归档目录权限也经检查,属主为postgres用户,权限正常。

(2)检查归档脚本与执行环境:

手动执行archive_command中的命令,模拟归档过程。发现当WAL文件较大或网络存储(NFS)瞬时延迟时,cp命令偶发性超时或返回错误,但数据库后台归档进程(archiver)仅记录了失败,并未重试或清理*.ready文件。* 检查归档目标存储(NFS挂载点)的可用空间和I/O状态,发现其在问题发生时间段存在间歇性高延迟。

(3)诊断核心问题:

根本原因:归档命令(cp)因外部存储(NFS)不稳定而间歇性失败,PostgreSQL的archiver进程在命令返回非零退出码时,认为该次归档失败。关键点在于:它不会自动删除已生成的*.ready标记文件。当下一个WAL段文件产生并再次标记为*.ready时,之前失败的*.ready文件就变成了“孤儿”,持续累积,导致归档目录被大量*.ready文件填满。
触发条件:网络存储的短暂性能波动,结合了过于简单的归档命令(缺乏重试和健壮的错误处理)。

3. 处理过程

处理过程遵循“先恢复,后根治”的原则,确保业务连续性的前提下解决问题。

阶段一:紧急恢复(清除非活动WAL文件)

(1)评估风险

确认积压的WAL文件对应的LSN位置(/archive目录下最旧的*.ready文件)仍晚于所有备库和基础备份所需的最旧LSN(可通过pg_controldata和备库复制状态确认)。确保清理这些文件不会影响未来的PITR(时间点恢复)。

(2)安全清理:

停止或暂停归档进程(可选):pg_ctl pause 或 临时将archive_command改为’/bin/true’并重载配置。但考虑到业务压力,我们选择了更动态的方式。* 编写并执行安全清理脚本。绝对禁止直接rm /archive/**.ready。

bash #!/bin/bash ARCHIVE\_DIR=/archive \# 找出所有未对应WAL文件的\*.ready文件(即“孤儿”文件) for ready\_file in $ARCHIVE\_DIR/\*\*.ready; do wal\_file=${ready\_file%\*.ready} if \[ ! -f $wal\_file \]; then echo "Removing orphaned ready file: $ready\_file" rm $ready\_file fi done

执行后,归档目录磁盘使用率立即下降。

阶段二:修复归档流程

(1)增强archive_command:将原先脆弱的cp命令替换为具有重试机制和更完善错误处理的脚本。

ini
archive_command = ‘/usr/local/bin/robust_archive.sh %p %f’

robust_archive.sh

脚本内容核心:

bash #!/bin/bash src=$1 dest\_name=$2 ARCHIVE\_DIR=/archive REMOTE\_LOCATION=backup-server:/pg\_archives/ MAX\_RETRIES=3 RETRY\_DELAY=5 for i in $(seq 1 $MAX\_RETRIES); do

使用rsync替代cp,支持断点续传和更多错误检查

if rsync -a $src $REMOTE\_LOCATION$dest\_name; then # 成功归档后,清理本地\*.ready文件,创建.done标记(可选) rm -f $ARCHIVE\_DIR/$dest\_name\*.ready touch $ARCHIVE\_DIR/$dest\_name.done exit 0 fi echo "Archive attempt $i failed for $dest\_name" sleep $RETRY\_DELAY done

所有重试失败后,记录严重错误,但返回失败让数据库知晓

logger -p local0.error “FATAL: Failed to archive WAL file $dest_name after $MAX_RETRIES attempts.”
exit 1

(2)配置调整与测试:

  • 将脚本部署到所有数据库服务器,设置正确的权限。
  • 临时创建一个测试WAL文件,手动执行新归档脚本,验证其功能。
  • 重载PostgreSQL配置:SELECT pg_reload_conf();。
  • 观察pg_stat_archiver视图,failed_count停止增长,last_archived_wal开始追赶当前WAL位置。

阶段三:监控与验证

(1)增强监控:在监控平台(如Zabbix、Prometheus)中添加对pg_stat_archiver中failed_count、last_archived_wal滞后度以及归档目录中*.ready文件数量的监控和告警。

(2)长期观察:连续观察24小时,确认归档流程稳定,无新的“孤儿”文件产生,归档延迟恢复正常水平。

4、经验总结

(1)归档命令的健壮性是生命线:切勿使用简单的cp或scp作为生产环境的archive_command。必须包含重试机制、详细的错误日志,并考虑使用如rsync等更可靠的传输工具。命令的返回值必须准确反映成功(0)或失败(非0)。

(2)“孤儿”*.ready文件是典型症状:归档目录磁盘爆满或*.ready文件堆积,首要怀疑归档命令本身或其所依赖的环境(网络、存储、权限)出现问题。pg_stat_archiver是诊断的第一站。

(3)清理操作务必谨慎:在清理任何WAL相关文件前,必须双重甚至三重确认这些文件不再被数据库实例、任何运行的备库或未来的恢复计划所需要。误删可能导致数据永久丢失或无法恢复。编写脚本进行有选择的清理,而非盲目删除。

(4)监控必须覆盖归档链路:除了数据库状态,还需监控归档目标存储的可用空间、I/O性能、网络连通性。对归档失败次数和归档延迟设置主动告警,实现“早发现,早处理”。5. 建立标准化与预案:将经过验证的、健壮的归档脚本和配置纳入数据库部署标准。针对此类问题,编写标准的应急处理预案(SOP),包括诊断步骤、安全清理方法和回滚方案,以便团队任何成员都能快速响应。

通过本次事件,我们不仅解决了一个具体的技术故障,更完善了数据库运维体系中关于日志归档的配置规范、监控维度和应急流程,显著提升了系统的稳定性和可维护性。

最后修改时间:2026-01-22 10:15:43
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论