PostgreSQL在写入数据时,所有变更都会先记录到WAL(预写式日志)中,WAL段文件写满后会循环复用。如果没有开启归档,被覆盖的WAL一旦丢失,就无法做基于时间点的恢复。archive_mode与archive_command正是PostgreSQL提供的WAL归档机制的核心参数,掌握它们的配置方法,是搭建备份恢复体系的第一步。

一、archive_mode参数详解
archive_mode决定PostgreSQL服务器是否启用WAL归档功能,它是一个静态参数,修改后必须重启数据库才能生效。它有三种取值:off、on和always。
当设置为off时,归档功能完全关闭,WAL段文件在写满后被直接复用。设置为on时,归档进程会在普通运行模式下启动。而always比较特殊,它意味着即使在数据库处于归档恢复模式(比如作为流复制的备库)时,也会继续归档从主库接收到的WAL,这个模式常用于构建级联备份的场景。
这个参数与wal_level密切相关。wal_level必须设置为replica或logical,归档功能才能正常工作。如果wal_level还是默认的minimal,即使打开了archive_mode,归档进程也不会有实际动作。典型配置如下:
# postgresql.conf 中的配置 wal_level = replica archive_mode = on archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'
修改后执行pg_ctl restart重启数据库,通过psql查询确认状态:
SHOW archive_mode; SHOW archive_command; -- 查看归档进程是否启动 SELECT pid, backend_type FROM pg_stat_activity WHERE backend_type = 'archiver';
二、archive_command的编写与占位符
archive_command是一个shell命令,PostgreSQL每归档一个WAL段文件就调用它一次。命令中最关键的是两个占位符:%p代表待归档WAL文件的完整路径,%f代表文件名。PostgreSQL要求该命令执行成功时返回退出码0,失败时返回非0,数据库会不断重试失败的归档,直到成功为止。
一个经典的写法是使用test配合cp,先判断目标文件是否已存在,避免重复归档造成数据被覆盖:
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'
如果目标位置在远程服务器,可以用scp或rsync。例如通过ssh推送到备份机:
archive_command = 'scp %p backup@192.168.1.100:/archive/%f'
使用远程方式时要提前配置好SSH免密登录,否则归档进程会因为密码交互提示而一直失败,WAL会在pg_wal目录中不断堆积,最终可能撑爆磁盘。
需要注意,archive_command只在主库上执行(always模式除外)。命令写错导致一直失败时,数据库不会丢数据,但pg_wal目录会持续膨胀,此时可以通过查询pg_stat_archiver视图来监控归档情况,包括成功次数、失败次数、最后一次失败的WAL文件名等信息,这是排查归档问题的重要入口。
三、归档验证与故障排查
配置完成后,验证归档是否生效是必不可少的步骤。最直接的验证方法是手动切换WAL:
SELECT pg_switch_wal();
执行后观察archive目录中是否出现了新的WAL文件(默认16MB一个段,文件名形如000000010000000000000001)。也可以通过pg_stat_archiver查看统计:
SELECT archived_count, last_archived_wal,
last_archived_time, failed_count, last_failed_wal
FROM pg_stat_archiver;排查归档故障时,建议按照以下顺序检查:第一,确认archive_mode是on且数据库已重启;第二,查看日志文件中是否有archive command failed的报错信息,日志会打印失败的命令和退出码;第三,手动以postgres操作系统用户身份执行归档命令,验证权限和路径是否正确;第四,检查归档目标目录的磁盘空间和文件系统权限。
特别强调权限问题:归档命令是以启动数据库的操作系统用户(通常是postgres)身份执行的,如果归档目录属于root或者其他用户,cp命令会因权限不足而失败。另外,归档目录所在文件系统的inode和空间也要纳入监控,很多生产事故正是归档目录写满后引发的连锁反应。
四、归档在恢复中的应用
归档的最终目的是为了恢复。当使用基础备份加WAL归档做恢复时,需要在备库或恢复实例的recovery配置中指定restore_command,它与archive_command正好是一对:一个负责存,一个负责取。
PostgreSQL 12及以上版本使用recovery.signal文件配合postgresql.conf中的参数,旧版本则使用recovery.conf,写法如下:
# PostgreSQL 12及以上的写法 restore_command = 'cp /archive/%f %p' # 触发恢复模式 touch /data/pg/recovery.signal
restore_command同样使用%f和%p占位符,含义与archive_command一致。恢复时PostgreSQL会依次调用restore_command获取需要的WAL文件,当命令返回非0且文件不存在时,恢复过程会认为WAL已用尽。配合recovery_target_time或recovery_target_lsn参数,就可以实现基于时间点的恢复(PITR),把数据库精确恢复到事故发生前的某个时刻。
对于大型生产环境,还建议使用pgBackRest、barman等专业备份工具替代简单的cp命令,它们提供了压缩、加密、并行传输和保留策略管理能力,能让归档体系更加健壮。但无论使用什么工具,底层依赖的仍然是archive_mode与archive_command这套机制,理解它们的原理是做好PostgreSQL备份运维的基础。
PostgreSQL归档配置archive_modearchive_commandWAL日志归档修改时间:2026-09-01 11:46:52