PostgreSQL的备份与恢复自动化并不是简单地把pg_dump命令丢进定时任务。真正可靠的机制必须同时覆盖备份生成、备份验证、恢复演练和保留策略四个环节,否则等到需要恢复时才发现备份文件损坏或缺失,往往已经造成不可逆的业务影响。本文围绕逻辑备份、物理备份与WAL归档三种方式,结合可落地的自动化脚本,把实施细节和容易忽略的坑梳理一遍。

一、先分清逻辑备份与物理备份的使用边界
很多团队在选型时容易把pg_dump和pg_basebackup混为一谈,认为都是备份,恢复时却发现问题。逻辑备份通过导出SQL语句或自定义格式转储数据库对象和数据,优势是可读性强、可以跨大版本恢复,缺点是备份和恢复时间较长,不适合超大库。物理备份直接复制数据目录和WAL文件,优势是恢复速度快、适合PB级场景,缺点是依赖平台和版本,不能跨架构直接使用。
pg_dump适合几十GB以内的业务库做每日全量备份。命令一般使用自定义格式,便于并行恢复和选择性还原。示例如下:
#!/bin/bash
BACKUP_DIR="/var/backups/postgresql"
DB_NAME="mydb"
PGUSER="postgres"
DATE=$(date +%F_%H%M%S)
mkdir -p "$BACKUP_DIR"
pg_dump -h 127.0.0.1 -U "$PGUSER" -Fc "$DB_NAME" > "$BACKUP_DIR/${DB_NAME}_${DATE}.dump"
if [ $? -eq 0 ]; then
echo "Backup success: ${DB_NAME}_${DATE}.dump"
else
echo "Backup failed" >&2
exit 1
fi
find "$BACKUP_DIR" -type f -name "*.dump" -mtime +7 -delete
如果数据库很大,比如超过100GB,每天逻辑备份会占用大量CPU和IO,这时候应该切换到pg_basebackup配合WAL连续归档,把恢复窗口缩短到分钟级甚至秒级。物理备份的核心不是简单的复制文件,而是从pg_basebackup生成的基准备份开始,持续归档WAL日志。这样一旦发生故障,可以先恢复基准备份,再回放后续WAL,做到时间点恢复。所以两者不是替代关系,而是不同规模、不同恢复目标下的组合方案。
| 维度 | 逻辑备份pg_dump | 物理备份pg_basebackup+WAL |
|---|---|---|
| 恢复粒度 | 可到单表 | 只能整库或表空间级 |
| 跨版本兼容 | 好 | 差,通常要求同大版本 |
| 恢复速度 | 慢 | 快 |
| 备份文件大小 | 较小,可压缩 | 接近数据目录大小 |
二、自动化调度:从一条cron到可观测的备份流水线
自动化调度的第一个误区是只配一条cron,不处理失败通知和日志。实际情况中,磁盘空间不足、网络抖动、数据库连接数打满都会导致备份脚本异常退出,如果没有日志和失败告警,备份可能已经停了好几周才被发现。建议把备份脚本独立出来,通过cron或systemd timer调用,脚本内部记录开始时间、结束时间、备份大小和退出码。
逻辑备份脚本可以配合系统调度器定时执行,下面是cron配置示例:
0 2 * * * /usr/local/bin/pg_backup.sh > /var/log/pg_backup.log 2>&1
物理备份同样需要自动化。pg_basebackup通常配合流复制协议运行,需要数据库中存在复制权限的账号。可以使用低峰期每日基准备份,WAL归档则通过archive_command持续推送到独立存储。下面是一个pg_basebackup命令示例:
pg_basebackup -h 127.0.0.1 -U replication -D /backup/base -Ft -z -P
cron和systemd timer两种调度方式各有优劣。cron简单直接,适合单机脚本。systemd timer可以设置随机延迟、失败重试和依赖关系,更适合生产环境。下面给出一个timer单元,每天凌晨2点执行备份服务。
[Unit] Description=PostgreSQL backup timer [Timer] OnCalendar=*-*-* 02:00:00 RandomizedDelaySec=300 Persistent=true [Install] WantedBy=timers.target
配合的service单元可以这样写,将标准输出和错误重定向到日志文件:
[Unit] Description=PostgreSQL logical backup [Service] Type=oneshot User=postgres ExecStart=/usr/local/bin/pg_backup.sh StandardOutput=append:/var/log/pg_backup.log StandardError=append:/var/log/pg_backup_error.log [Install] WantedBy=multi-user.target
三、恢复演练才是备份的最后闭环
只备份不验证等于没备份。恢复演练至少每月做一次,做法是在测试环境使用最近的一份备份完整恢复,再执行应用级检查。逻辑备份的恢复步骤通常是先创建空库,再使用pg_restore导入。示例:
createdb -h 127.0.0.1 -U postgres restored_db pg_restore -h 127.0.0.1 -U postgres -d restored_db /backup/mydb_20240301.dump
如果备份文件是tar格式,需要先解包再恢复。恢复完成后不要只看命令返回成功,还要检查行数、关键表数据以及应用功能是否正常。
物理备份的恢复稍复杂,但思路明确。先把pg_basebackup生成的基准备份解压到数据目录,然后创建recovery.signal空文件,并配置restore_command让PostgreSQL从WAL归档位置自动取回WAL。示例:
touch ${PGDATA}/recovery.signal
启动实例后,数据库会自动进入恢复状态,回放到指定的目标时间点后转为正常模式。恢复过程中如果发现WAL没有及时被识别,先检查归档目录权限以及restore_command的返回码。
常见问题大多集中在权限和路径。恢复时数据目录的所有权必须是postgres用户,restore_command中的命令要以postgres身份执行,归档目录需要可读。另一个高频错误是忘记修改postgresql.conf中的端口和监听地址,导致恢复实例与生产实例冲突。建议恢复环境使用独立端口,并用pg_ctl明确指定数据目录启动。
- 备份文件不要和数据库放在同一块磁盘,否则磁盘故障同时带走生产数据和备份。
- 不要只保留一份备份,至少保留最近7天的每日备份和最近4次的周备份。
- 逻辑备份无法替代WAL归档,如果业务允许分钟级恢复,必须搭建连续归档。
- 每次恢复演练后记录耗时,用来评估RTO是否符合预期。
PostgreSQL备份和恢复自动化没有统一答案,关键是先确定恢复目标,再选择逻辑备份、物理备份或组合策略。把调度、日志、验证、演练串成闭环,才能避免备份数据在关键时刻失效。
PostgreSQL备份自动化恢复pg_dump修改时间:2026-10-05 17:29:51