PostgreSQL备份数据库用pg_dump怎么操作

文章导读
用 pg_dump 备份 PostgreSQL,核心是把“备份哪个库、恢复到什么状态、谁来执行、文件放哪里”这几件事先定下来,再选参数。pg_dump 输出的是逻辑备份(SQL 脚本或自定义归档),它不替代 WAL 归档和基础备份做时间点恢复;如果目标只是单库迁移、版本升级前的留档、或把某个库复制到测试环境,pg_dump 通常是够用的起点。先在测试库跑通一次“备份—恢复”,再考虑放到生产定时任务
📋 目录
  1. A 先确认当前场景和目标
  2. B 按这个顺序处理
  3. C 改完后怎么验证
  4. D 容易忽略的边界
A A

用 pg_dump 备份 PostgreSQL,核心是把“备份哪个库、恢复到什么状态、谁来执行、文件放哪里”这几件事先定下来,再选参数。pg_dump 输出的是逻辑备份(SQL 脚本或自定义归档),它不替代 WAL 归档和基础备份做时间点恢复;如果目标只是单库迁移、版本升级前的留档、或把某个库复制到测试环境,pg_dump 通常是够用的起点。先在测试库跑通一次“备份—恢复”,再考虑放到生产定时任务里。

判断标准很简单:需要单库级、可跨版本、可选择性恢复的备份,用 pg_dump;需要整实例一致性快照或时间点恢复,应配合 pg_basebackup 与 WAL 归档。操作上建议用普通数据库账号执行,加 -Fc 输出自定义归档,用 pg_restore 验证可读性,并确认备份文件落在有空间的独立磁盘上。边界在于大库耗时长、会持有较长事务快照,对业务有影响时需要错峰执行,不能把它当作零影响方案。

先确认当前场景和目标

动手前先确认四件事,任何一项不清都会让备份“看起来成功、实际不能用”。第一是备份对象:只要一个业务库,还是需要全实例的角色、表空间、所有库。pg_dump 一次只处理一个数据库,全实例需要配合 pg_dumpall 或逐个库循环。第二是恢复目标:恢复到同版本实例,还是跨大版本迁移;跨大版本时通常建议用 SQL 纯文本格式(-Fp)或让 pg_restore 处理自定义格式,并先在目标版本的空库上试恢复。第三是权限:执行者至少需要对被备份库有读权限,是否能读到全部表取决于账号角色;如果库里有大对象、外部表或特定 schema,需要提前确认。第四是落盘位置与保留策略:备份文件通常比原库小,但大库仍可能几十 GB,要确认目标目录剩余空间、是否与数据目录同盘。

还要判断执行窗口。pg_dump 在运行期间会建立一致性快照,对业务主要影响是 IO 和长时间事务对 vacuum 的阻碍;库越大、并发写入越多,越需要放到低峰期。可以先在一个次要库或小库上估算耗时,再决定是否在生产直接跑。

按这个顺序处理

第一步,确认连接信息与版本,避免用高版本 pg_dump 连低版本服务端时出现不兼容提示。命令中的主机、端口、库名、用户名都要替换成自己的环境值:

psql -h 127.0.0.1 -p 5432 -U backup_user -d your_db -c "select version();"
pg_dump --version

第二步,选择输出格式并执行备份。日常留档建议用自定义归档格式 -Fc,它压缩、支持 pg_restore 选择性恢复,也便于并行恢复;需要人眼可读的 SQL 脚本时用默认纯文本。下面的片段中 your_db、backup_user、路径都需替换:

# 自定义归档,适合归档和迁移
pg_dump -h 127.0.0.1 -p 5432 -U backup_user \
  -Fc -Z 6 \
  -f /backup/pg/your_db_$(date +%Y%m%d_%H%M).dump \
  your_db

# 纯文本 SQL,适合小库或需要人工查看
pg_dump -h 127.0.0.1 -p 5432 -U backup_user \
  -Fp -f /backup/pg/your_db_$(date +%Y%m%d).sql \
  your_db

第三步,把认证信息从命令行里拿掉。交互执行时可以直接输入密码;放进定时任务时建议使用 ~/.pgpass 或服务级的密码文件,权限设为仅属主可读,避免密码出现在进程列表和脚本里。示例骨架如下,host、port、db、user、password 都要替换:

# ~/.pgpass 内容格式:hostname:port:database:username:password
127.0.0.1:5432:your_db:backup_user:your_password

chmod 600 ~/.pgpass

第四步,如果备份多个库或需要角色、表空间,改用 pg_dumpall 或写循环。pg_dumpall 输出全局对象,通常配合 -f 落盘;循环单库备份时注意每个库单独一个文件名,别互相覆盖:

PostgreSQL备份数据库用pg_dump怎么操作
# 全实例(含角色等全局对象),按需替换连接参数
pg_dumpall -h 127.0.0.1 -p 5432 -U backup_user \
  -f /backup/pg/all_$(date +%Y%m%d).sql

第五步,为定时任务加保护:设置超时、检查退出码、备份完成后判断文件大小是否明显异常。脚本里不要只看“任务跑了”,要看 pg_dump 的返回码,非 0 就应当告警,而不是继续覆盖上一份可用备份。

改完后怎么验证

验证不能只看备份命令有没有报错。最直接的动作是把备份恢复到一个临时库,再做对象和行数抽查。自定义归档先列出内容确认可读:

# 查看归档里包含哪些对象,不真正导入
pg_restore -l /backup/pg/your_db_YYYYMMDD_HHMM.dump | head -n 30

然后在临时实例或临时库上恢复。纯文本用 psql 导入,自定义归档用 pg_restore;恢复目标库建议新建,不要覆盖现有库:

createdb -h 127.0.0.1 -p 5432 -U backup_user restore_check
pg_restore -h 127.0.0.1 -p 5432 -U backup_user \
  -d restore_check /backup/pg/your_db_YYYYMMDD_HHMM.dump

# 导入后核对关键表的行数与最近数据
psql -h 127.0.0.1 -p 5432 -U backup_user -d restore_check \
  -c "select count(*) from your_table;"

预期信号是:pg_restore 正常结束、退出码为 0,关键表存在、行数与源库同一时刻的预期数量一致,序列和约束可用。若只想验证备份文件完整性而不导入,pg_restore -l 能正常列出目录即可作为初步信号,但这不能替代一次真实恢复。恢复过程通常会输出若干权限或已存在对象的提示,需要逐条看是否存在真正失败项。

容易忽略的边界

pg_dump 不是物理备份,不保证时间点恢复能力,也不备份 WAL。如果业务目标是“误删数据后回到某个时刻”,仅靠 pg_dump 做不到,需要另外的基础备份和 WAL 归档。大库备份期间会持有一个较长的快照,长事务可能影响 autovacuum,并发写入高时建议错峰,必要时接受备份时间变长而不是强行压低。

版本兼容需要单独确认:用较低版本的 pg_dump 去连较高版本服务端通常会被拒绝,建议 pg_dump 版本不低于服务端主版本,跨大版本迁移先在小库上试恢复。权限方面,普通账号可能看不到部分 schema 或大对象,备份“成功”但内容缺失是常见问题;恢复账号也需要目标库的建表权限。文件落盘位置要考虑磁盘空间和权限,备份文件不要和数据目录放同一块盘。最后,备份文件本身应当有保留和清理策略,并定期做一次真实恢复演练;如果当前环境不具备可靠恢复条件,回退方案是保留最近的纯文本 SQL 备份以便人工排查,同时尽快建立可验证的物理备份链路。