AI时代首先数据库-PostgreSQL实战笔记 | 19 PostgreSQL逻辑备份:pg_dump与pg_dumpall

上一篇我们聊了索引的 B-tree 结构和失效场景。这一篇,我们进入运维中最不能心存侥幸的环节:备份。逻辑备份是 PostgreSQL 日常运维中使用频率最高的备份方式,但它也是最容易被"想当然"对待的------很多人以为跑通了 pg_dump 就等于有了备份,直到真正需要恢复时才发现文件损坏、对象缺失、或者根本不知道该用哪个工具恢复。这一篇,我们把 pg_dump、pg_dumpall、pg_restore 三个工具的分工、四种格式的选择、并行备份的边界,以及"备份文件如何验证可恢复"这个核心问题,逐一拆开。

一、逻辑备份到底在备份什么?

逻辑备份的本质是:通过数据库连接读取对象定义和数据,输出为 SQL 脚本或归档文件 。它不复制任何物理数据文件,而是重新"描述"数据库------建表语句、数据 COPY 流、索引和约束定义。

这个本质决定了逻辑备份的两个核心特征:

第一,它是一致性快照,不是锁表。 pg_dump 利用 PostgreSQL 的 MVCC 机制,在启动时获取一个一致性快照,整个备份过程基于这个快照读取数据,备份期间对数据库的更新不会进入备份文件,业务读写也不会被阻塞 。你不需要在业务低峰期执行 pg_dump,但需要知道:备份文件反映的是"备份启动那一刻"的状态,而不是"备份结束那一刻"。

第二,它不包含 WAL,无法做 PITR。 逻辑备份没有时间点恢复能力,无法恢复到"某个具体时刻之前"的状态。这是它和物理备份最根本的能力边界。

二、三个工具的分工:一张表说清

很多人混淆 pg_dump 和 pg_dumpall,核心原因是没分清"单库"和"集群全局对象"的边界。

工具 备份范围 是否包含角色/表空间 输出格式
pg_dump 单个数据库 不包含 全部四种格式
pg_dumpall 整个集群(所有库 + 全局对象) 包含 仅 plain 文本
pg_restore --- --- 恢复非 plain 归档(custom/directory/tar)

关键规则:pg_dump 不备份角色(roles)和表空间(tablespaces)定义。 如果你用 pg_dump 备份了业务库,恢复到新集群后,表可能无法正常访问,因为角色不存在、表空间路径缺失。

正确的集群级迁移策略是两步走 :先用 pg_dumpall --globals-only 导出全局对象(角色、表空间、授权),再对每个数据库分别执行 pg_dump。不要直接用 pg_dumpall 导出全部数据------它只能生成 plain 文本,不支持并行,大集群下恢复速度极慢。

三、四种格式:plain、custom、directory、tar

pg_dump 支持四种输出格式,选择格式直接决定了你"能不能并行、能不能选择性恢复"。

plain(-Fp):纯 SQL 脚本

输出可读的 SQL 文本,用 psql -f 恢复。优点是可编辑、可审查、跨版本兼容性好 ;缺点是无法使用 pg_restore 选择性恢复,大库恢复慢,且不支持并行。适合小库、需要人工审查的场景。

custom(-Fc):生产最常用

二进制归档,默认压缩 ,支持 pg_restore 进行选择性恢复(单 schema、单表、单扩展)和并行恢复 ,但不支持并行备份。这是日常单库备份的推荐默认格式。

directory(-Fd):唯一支持并行备份的格式

输出为一个目录,内部按表和段拆分成多个文件,唯一支持 -j N 并行备份的格式,同时支持并行恢复。大库备份的首选。

tar(-Ft):兼容但受限

tar 归档,不支持压缩,选择性恢复能力有限。实际生产中很少作为首选。

格式选择的一句话原则: 日常单库 → -Fc;大库追求备份速度 → -Fd -j N;需要可读 SQL 做审查 → -Fp;-Ft 基本可以忽略。

四、并行备份与并行恢复:边界必须搞清楚

这是最容易踩坑的地方。

并行备份只属于 directory 格式。 pg_dump -Fd -j 4 -f /backup/mydb_dir 会用 4 个并发连接同时导出不同表的数据。custom 格式不支持 -j,即使你写了 pg_dump -Fc -j 4,-j 也会被忽略或报错。

并行恢复 custom 和 directory 都支持。 pg_restore -j 4 -d target_db mydb.dump 可以并行加载数据。

所以大库的典型组合是:pg_dump -Fd -j 8 并行备份,pg_restore -j 8 并行恢复。custom 格式则只能"串行备份、并行恢复"。如果备份窗口本身就是瓶颈,directory 是唯一解。

五、pg_restore 的段拆分:为什么恢复速度能快起来

非 plain 格式的归档内部被拆分为三个段:pre-data → data → post-data。

  • pre-data:表 DDL、类型、函数(不含索引、外键、触发器);
  • data :COPY 数据流、序列值、大对象内容;
  • post-data:索引、外键、触发器、约束、规则。

这个拆分让恢复可以按"先建表 → 并行灌数据 → 最后建索引 "的顺序执行。post-data 中的索引在数据加载完成后一次性构建,比逐行维护索引快得多。这也是为什么 pg_restore 恢复大库时,即使不开并行,也通常比 psql -f 执行 plain SQL 更快------plain 脚本中的索引语句会在数据加载过程中逐步执行,每次插入都要维护 B-tree。

pg_restore 还支持选择性恢复:-t table_name 只恢复某张表,-n schema_name 只恢复某个 schema,-l 列出归档内容先确认对象清单。这是逻辑备份相比物理备份的核心优势之一------物理备份只能整体恢复,逻辑备份可以只捞回一张表。

六、备份文件如何验证"可恢复"?

这是本篇最关键的实操问题。生成了备份文件,不等于拥有了一份可用的备份。

验证分三个层次,成本递增,可信度也递增。

第一层:文件可读性检查

bash 复制代码
# custom/directory/tar:列出归档目录,确认 TOC 可读
pg_restore --list mydb.dump > /dev/null

# plain:语法检查
psql --set=ON_ERROR_STOP=on -f mydb.sql --dry-run  # 部分版本支持

pg_restore -l 能正常输出对象清单,说明归档结构完整,文件没有在传输或存储中损坏。

第二层:恢复到测试库,跑冒烟查询

这是最基本的可靠验证。创建一个临时数据库,用 pg_restore --exit-on-error 恢复,然后对核心表执行 COUNT(*) 或业务关键查询,与源库对比。

bash 复制代码
createdb -h restore_host -U postgres mydb_verify
pg_restore --exit-on-error -h restore_host -U postgres -d mydb_verify mydb.dump
psql -h restore_host -U postgres -d mydb_verify -c "SELECT count(*) FROM orders;"

--exit-on-error 让 pg_restore 在第一个错误时立即退出,而不是继续"带病恢复"。没有这个参数,恢复可能"成功"结束,但部分对象缺失,等到业务上线才发现问题。

第三层:自动化恢复演练

生产环境应该把"恢复到测试库"做成定时任务,而不是靠人工偶尔想起。社区中的实践是:备份完成后自动触发恢复脚本,恢复完成后自动对比关键表的行数,不一致则告警。备份的可信度不来自"备份成功"的日志,而来自"恢复成功且数据一致"的验证。

一个容易被忽略的细节:物化视图的数据不会被 pg_dump 导出,只导出定义 。恢复后物化视图是空的,状态为未填充,必须手动执行 REFRESH MATERIALIZED VIEW。如果你的备份验证发现某个"表"的行数为零,先确认它是不是物化视图。

七、逻辑备份 vs 物理备份:怎么选

维度 逻辑备份(pg_dump) 物理备份(pg_basebackup + WAL)
备份单位 库 / schema / 表 整个数据目录
跨版本兼容 ✅ 跨大版本、跨架构 ❌ 版本必须严格一致
选择性恢复 ✅ 单表、单 schema ❌ 只能整体恢复
恢复速度 较慢 快
PITR ❌ 不支持 ✅ 支持
对业务影响 不锁表,基于快照 依赖 WAL 归档,可在线
适合场景 迁移、环境克隆、误删表找回、小库日常备份 大库灾备、快速全量回滚、时间点恢复

两者不是替代关系,而是互补关系。 逻辑备份负责"灵活性"------跨版本、单对象、迁移;物理备份负责"速度和完整性"------大库快速恢复、PITR。生产环境的成熟策略通常是:物理备份做灾备底座,逻辑备份做细粒度兜底和迁移工具。

八、总结

主题 核心结论
一致性 MVCC 快照,不锁表,备份期间更新不入备份
工具边界 pg_dump 单库、不含角色/表空间;pg_dumpall 集群、仅 plain
格式选择 custom 日常首选;directory 唯一支持并行备份;plain 可读但恢复慢
并行边界 并行备份仅 directory;并行恢复 custom/directory 都支持
恢复拆分 pre-data → data → post-data,索引最后建
验证 至少恢复到测试库 + --exit-on-error + 行数对比;物化视图需手动 REFRESH
选型 逻辑与物理互补,不是替代

一句话:逻辑备份的价值不在于"备份"这个动作,而在于"恢复"这个能力。没有经过恢复验证的备份文件,只是一堆占空间的字节。

下一篇,我们进入物理备份:pg_basebackup 与 PITR------为什么物理备份能做时间点恢复?pg_basebackup 和 WAL 归档如何配合?


思考题:

你平时用 pg_dump 备份时,默认格式是 custom 还是 plain?有没有遇到过 pg_dump "成功"但恢复时才发现对象缺失、物化视图为空、或者角色不存在的情况?另外,你的备份策略里,物理备份和逻辑备份各自承担什么角色?欢迎在评论区聊聊。

相关推荐
啵啵啵鱼1 小时前
九、JDBC 操作 MySQL 数据库
android·数据库·mysql
handonch1 小时前
MySQL → Kingbase PG模式 高频SQL替换清单
数据库·mysql·postgresql
姜鱼问生1 小时前
Kuma SQLite 备份坑
数据库·sqlite
水无痕simon1 小时前
15 MySQL是怎么保证高可用的?
数据库·mysql
漫步人生走在路上1 小时前
外贸SEO中的品牌词与产品词策略:大卖家和小卖家的不同打法
大数据·javascript·网络·数据库·人工智能·搜索引擎
张小姐的猫1 小时前
【MySQL】数据类型
android·linux·数据库·c++·mysql·adb·php
泡海椒1 小时前
JQuick-SQL LIMIT 分页:限制行数与偏移查询
数据库·sql
flytalei1 小时前
逐浪笔记 GitOps 实战:Jenkins 构建、Argo CD 同步与 Git 回滚
笔记·git·jenkins
叼烟扛炮2 小时前
Linux 学习笔记(八):GCC 编译器的四大阶段与链接原理
linux·笔记·学习