开启归档模式的PostgreSQL实例,会把写满的WAL段通过archive_command交给外部命令处理。这个过程数据库自身不做重试保证,一旦命令持续失败,pg_wal目录会不断堆积文件,严重时撑爆磁盘。而很多团队的归档故障都是在磁盘告警响起之后才发现的,其实pg_stat_archiver视图早就把线索写在里面了,只是没人去看。

pg_stat_archiver视图字段详解
pg_stat_archiver是一个统计视图,位于pg_catalog schema下,任何角色都可以直接查询。它记录的是从实例启动以来(或上次执行pg_stat_reset之后)的归档统计信息,核心字段可以分为三类:成功统计、失败统计和当前状态。
成功相关的字段包括archived_count(成功归档的文件总数)和last_archived_wal(最近一次成功归档的WAL文件名)以及last_archived_time(最近成功时间)。失败侧对应failed_count(失败次数)、last_failed_wal和last_failed_time。要注意的是,一旦某次归档成功,last_failed_wal和last_failed_time会被清零重置,所以不能只看这两个字段判断当前是否有问题,failed_count才是历史累积值。
当前状态字段stats_reset表示统计重置时间点,配合stats_reset可以算出归档速率。下面这条SQL能一次性拿到关键信息:
SELECT
archived_count,
last_archived_wal,
last_archived_time,
failed_count,
last_failed_wal,
last_failed_time,
stats_reset
FROM pg_stat_archiver;另外还有一个容易被忽略的字段last_failed_wal,它记录的是失败时刻正在处理的WAL段。如果这个文件名长期不变,说明归档进程卡在同一个文件上反复失败,通常意味着外部命令返回了非零退出码。
如何判断归档进度是否异常
光看单次查询结果很难下结论,监控归档进度的关键在于对比「数据库当前产生的WAL位置」和「归档器已经推进到的位置」。数据库侧可以用pg_current_wal_lsn()拿到当前LSN,而归档侧的last_archived_wal代表最后一个归档成功的段文件。
判断滞后程度的思路有两种。第一种是时间维度:计算last_archived_time与当前时间的差值,如果这个差值明显超过wal_keep_size对应的产生周期,或者超过平时归档间隔的数倍,就可以认为归档滞后。第二种是文件维度:观察pg_wal目录下ready状态文件的数量,正常情况下ready文件应该在归档成功后被迅速改成done,堆积过多说明归档速度跟不上生成速度。
SELECT
now() - last_archived_time AS lag_interval,
pg_size_pretty(
pg_wal_lsn_diff(pg_current_wal_lsn(),
pg_walfile_name_reverse(last_archived_wal))
) AS lag_size
FROM pg_stat_archiver;上面SQL中的lag_size表示当前写入位置与最近归档文件起始位置之间的数据量,是衡量归档落后程度最直观的指标。经验上,lag_size持续超过几个GB就值得排查,说明archive_command执行太慢或者失败了。
结合archive_command排查失败原因
当failed_count持续增长时,下一步是定位archive_command本身的问题。PostgreSQL要求归档命令成功时返回退出码0,非零即视为失败。常见的坑包括:目标目录磁盘满、SSH密钥权限不对、目标端目录未创建、以及命令本身写法错误。如果archive_command里配置了%p和%f参数,务必确认%p在PostgreSQL 13之前的版本中路径拼接方式是否正确。
排查时建议开启详细日志,把归档命令的输出重定向到日志文件,例如下面这种写法:
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f 2>> /var/log/pg_archive.log'
这段命令先用test判断目标文件是否已存在,避免重复归档,然后用cp拷贝,标准错误追加写入日志。查看/var/log/pg_archive.log基本能定位九成以上的失败原因。
还要注意归档进程archiver每次只会调用一个archive_command实例,如果归档速度跟不上生成速度,比如使用了同步压缩或者网络传输到异地,WAL会持续堆积。这种情况下可以改用pgbackrest、barman这类支持并行归档的工具,它们内置队列和多进程机制,归档吞吐能力远超单条shell命令。
落地的监控脚本与告警阈值
把前面的判断逻辑固化成监控脚本,接入Zabbix或Prometheus都能用。核心SQL可以封装成一个函数,输出归档滞后秒数、失败次数增量和ready文件堆积数三个指标。失败次数增量建议按固定间隔采样做差值,比直接用绝对值更可靠,因为failed_count是累积值。
SELECT
EXTRACT(EPOCH FROM now() - last_archived_time)::int AS archive_lag_seconds,
failed_count,
last_failed_wal
FROM pg_stat_archiver;告警阈值可以这么定:archive_lag_seconds超过600秒触发警告,超过1800秒触发严重告警;两次采样之间failed_count差值大于0就立即告警,因为哪怕只有一次失败也意味着外部环境出了变化。pg_wal目录下ready文件数超过10个属于警告,超过50个属于严重。这些数值需要根据业务写入量微调,高写入场景可以适当放宽时间阈值但收紧文件数阈值。
最后提一句,执行SELECT pg_stat_reset();会清空pg_stat_archiver的统计,生产环境谨慎使用。如果只想验证归档链路是否通畅,可以手动执行SELECT pg_switch_wal();强制切换WAL段,观察last_archived_wal是否在短时间内更新,这是最快速的自检手段。归档监控看似不起眼,却是数据安全链条上不可缺失的一环,建议纳入日常巡检清单。
pg_stat_archiverWAL归档监控PostgreSQL归档修改时间:2026-09-16 14:36:40