上周帮一个朋友恢复数据,备份他的恢复PostgreSQL实例在云上跑了两年,从来没做过备份。备份硬盘故障,恢复数据全丢。备份他问我有没有办法从WAL日志里捞出来——没有基础备份,恢复WAL就是备份一堆废纸。这事让我觉得有必要把备份恢复这件事写清楚。恢复
逻辑备份:pg_dump 和 pg_dumpall
pg_dump 是备份最常用的工具,导出一个数据库。恢复它生成的备份是SQL脚本或者自定义格式的归档文件。自定义格式(-Fc)更灵活,恢复配合 pg_restore 可以只恢复某张表、备份某个schema,恢复还能并行恢复。备份
pg_dump -Fc -h localhost -U postgres mydb > mydb.dump恢复的时候:
pg_restore -d mydb_new -j 4 mydb.dump-j 4开四个并行任务,大库能快不少。但注意,并行恢复只对自定义格式有效,纯SQL文件没这个待遇。pg_dumpall 则是全实例级别的,包含所有数据库和全局对象(角色、表空间)。它只能导出SQL文本,恢复时用psql直接灌。数据量大的话会很慢,而且中间出错不好定位。
逻辑备份的硬伤:它不保证一致性快照跨数据库。pg_dump 对单个库用可重复读事务,能拿到一致快照,但 pg_dumpall 是逐个库串行导,库和库之间的数据可能对不上。另外,大库导出时间长,锁虽然不重,但IO压力实打实。
物理备份:pg_basebackup 与归档
物理备份才是生产环境的正路。pg_basebackup 直接拷贝数据目录,速度快,恢复也快。它依赖WAL归档来保证一致性——备份期间产生的WAL必须保留,恢复时重放。
pg_basebackup -D /backup/base -Ft -z -P -h localhost -U replicator-Ft打包成tar,-z压缩,-P显示进度。-X stream选项能把备份过程中需要的WAL一起打包进去,省得手动去归档目录捞。要恢复到一个时间点,得配置
restore_command和recovery_target_time。比如误删了表,恢复到删之前那一秒。我见过有人把recovery_target_time写错时区,结果恢复到错误的时间点,白忙一场。WAL归档是物理备份的命根子。没有归档,你只能恢复到基础备份完成的那一刻。配置很简单:
archive_mode = on archive_command = 'cp %p /archive/%f'但
archive_command返回非零,WAL就会堆积在pg_wal目录,撑爆磁盘。生产环境建议用 pgBackRest 或 WAL-G 这类工具管理,它们处理重试、压缩、上传对象存储,比裸写脚本靠谱得多。几个容易踩的坑
备份文件权限。pg_dump 导出的文件默认是当前用户可读,如果包含敏感数据,记得
chmod 600。pg_basebackup 的tar包也一样。恢复时的角色和权限。逻辑备份恢复到一个新实例,如果原库有自定义角色,pg_dump 不会自动创建它们(pg_dumpall 会)。恢复会报错说角色不存在。要么先手动建角色,要么用
--no-owner跳过所有权设置。版本兼容。pg_dump 高版本导低版本通常没问题,反过来不行。pg_basebackup 要求主备版本一致,小版本可以不同,大版本必须相同。
测试恢复。这是最容易被忽略的一步。备份脚本跑成功不代表能恢复。定期拿备份在另一台机器上实际恢复一次,验证数据完整性和恢复时间。我见过备份文件损坏了三个月没人发现,直到真出事。
监控归档。
pg_stat_archiver视图里failed_count持续增长就是警报。WAL归档断了,物理备份的恢复能力就停在断点之前。说到底,备份策略取决于你能承受丢多少数据。逻辑备份加WAL归档,RPO可以做到秒级。只有pg_dump,RPO就是上次导出的时间点。先想清楚这个,再选工具。
顶: 8923踩: 28821






评论专区