4. 逻辑备份与恢复工具选型
PostgreSQL 的逻辑备份工具并非“一个命令走天下”。pg_dump、pg_dumpall、pg_restore、COPY 四者面向的对象层级、并发模型、一致性快照机制和恢复粒度差异很大。选型错误往往不会在备份时暴露,而是在恢复现场才集中爆发:要么恢复不出全局角色导致应用连不上,要么单表恢复被迫重放整库,要么并行度上不去导致窗口超时。本节先厘清四者的能力边界,再给出可落地的备份策略组合。
四类工具的能力边界
pg_dump 是单数据库逻辑导出工具,导出对象包括表结构、数据、索引、约束、触发器、函数、序列当前值等,但不包含角色、表空间定义和数据库本身的创建语句。它支持 -Fc(自定义格式)、-Fd(目录格式)、-Ft(tar)、-Fp(纯 SQL)四种输出。其中只有目录格式 -Fd 支持 -j 并行导出,因为并行导出的本质是多个工作进程各自导出一部分表,再写入独立文件。
pg_dumpall 是集群级导出工具,核心价值在于导出全局对象:角色、表空间、以及各数据库的创建语句。它内部对每个数据库仍调用 pg_dump,因此单库部分可以并行,但全局对象部分(--globals-only)是串行的。它默认输出纯 SQL 脚本,恢复时用 psql 顺序执行,无法使用 pg_restore 的并行恢复能力。
pg_restore 不是备份工具,而是 pg_dump 自定义/目录/tar 格式的恢复工具。它的关键能力是选择性恢复(-t 指定表、-n 指定模式、-l 列出归档内容)和并行恢复(-j)。并行恢复对目录格式最有效,因为每个表的数据文件相互独立,多个进程可以同时 COPY 入库。
COPY 是表级数据搬运命令,服务端 COPY 与客户端 \copy 均可。它只处理数据行,不处理 DDL、索引、约束、权限。优势是速度极快、格式灵活(CSV、二进制),适合大批量数据导入导出、跨库表级同步、以及 ETL 中间环节。它不提供跨表一致性快照,除非显式包在 BEGIN ... REPEATABLE READ 事务中。
一致性保证的差异
pg_dump 默认在导出开始时开启一个可重复读事务(REPEATABLE READ),因此同一数据库内所有表的导出数据来自同一个快照,具备库内一致性。但要注意:pg_dump 不保证跨数据库一致性,因为每个数据库是独立连接、独立快照。pg_dumpall 逐库导出,各库快照时间点不同,因此集群级备份不具备全局一致性。COPY 单独执行时每条语句各自快照,多表导出若不在同一事务内,可能出现表间数据时间点不一致。
并行能力与恢复粒度对照
| 工具 | 导出并行 | 恢复并行 | 恢复粒度 | 包含全局对象 |
|---|---|---|---|---|
| pg_dump -Fd | 支持 -j | 需配合 pg_restore -j | 库 / 模式 / 表 | 否 |
| pg_dump -Fc | 不支持 | pg_restore -j 支持 | 库 / 模式 / 表 | 否 |
| pg_dumpall | 仅单库部分 | psql 串行 | 集群 / 库 | 是 |
| COPY | 需自行分片 | 需自行分片 | 表 / 行 | 否 |
并行度并非越高越好。pg_restore -j 的每个工作进程都会占用一个数据库连接并产生 WAL 写入压力,通常建议 -j 不超过 CPU 核数,且恢复期间监控 pg_stat_activity 与 WAL 生成速率。对于含大量小表的库,并行收益有限;对于少数超大表,并行恢复提升明显。
选型决策与策略组合
实际生产环境很少只用一种工具,常见组合是:pg_dumpall --globals-only 负责角色与表空间定义,pg_dump -Fd -j 负责各业务库数据,两者配合 pg_restore -j 完成快速恢复。对于超大规模单表或跨库数据交换,用 COPY 做补充。下面这张图展示了从备份对象到工具选择、再到恢复路径的对应关系。
制定备份策略的实操要点
一个可执行的策略至少回答四个问题:备份什么、用什么工具、多久一次、如何验证。以下给出一个面向中等规模业务库的示例配置,参数属于教学示例,实际需按数据量与窗口调整。
# 1. 全局对象备份(每日一次,保留 30 天)
pg_dumpall -h 10.0.0.10 -p 5432 -U postgres \
--globals-only -f /backup/globals_$(date +%F).sql
# 2. 业务库目录格式并行导出(每日一次)
pg_dump -h 10.0.0.10 -p 5432 -U postgres \
-Fd -j 4 -f /backup/orderdb_$(date +%F) orderdb
# 3. 恢复:先全局对象,再并行恢复业务库
psql -h 10.0.0.20 -U postgres -f /backup/globals_2025-01-15.sql
pg_restore -h 10.0.0.20 -U postgres -d orderdb \
-j 4 --no-owner /backup/orderdb_2025-01-15
# 4. 单表应急恢复(从目录格式中只取一张表)
pg_restore -h 10.0.0.20 -U postgres -d orderdb \
-t public.orders --data-only /backup/orderdb_2025-01-15
验证环节不可省略。备份完成后至少做三件事:用 pg_restore -l 确认归档目录可读且对象数量符合预期;在测试实例上实际恢复一次并比对关键表行数;记录备份耗时与恢复耗时,作为窗口规划依据。对于 COPY 导出的 CSV,恢复前应确认目标表已存在且列顺序一致,否则会因列错位导致数据污染。
-Fd -j 目录格式,恢复时同样用 -j 并行,通常比纯 SQL 脚本快数倍。全局对象单独用 pg_dumpall --globals-only 每日导出,体积小、恢复快,不必与业务库数据捆绑。最后强调恢复粒度的选择逻辑:需要整库回滚用 pg_dump + pg_restore;需要跨集群重建用 pg_dumpall + psql;只需要一张表或一个模式用 pg_restore -t/-n;只需要数据行、不需要 DDL 用 COPY。把工具能力与恢复目标对齐,备份策略才真正可用。