4. 逻辑备份恢复工具pg_restore与psql
pg_dump 负责“导出”,而真正把逻辑备份还原回数据库,主要依赖两个工具:psql 和 pg_restore。二者分工的关键在于备份格式:psql 只能处理纯文本(plain)格式的 SQL 脚本,它本质上是把脚本逐条发送给服务器执行;pg_restore 则专门处理自定义(custom)、目录(directory)和 tar 格式,这些格式带有对象目录、依赖关系和元数据,因此 pg_restore 能够实现选择性恢复、并行恢复和重排执行顺序。理解这一点,是掌握恢复选项的前提。
一、两种恢复路径与核心选项
纯文本备份的恢复最直接:
psql -h 127.0.0.1 -U app -d appdb -v ON_ERROR_STOP=1 -f appdb.sql
这里 -v ON_ERROR_STOP=1 非常关键。默认情况下 psql 遇到错误会继续往下执行,导致“部分成功”的假象;加上它之后,一旦出错立即中止,便于定位问题。若脚本中包含 CREATE DATABASE,通常需要先连到 postgres 库执行,或使用 -d postgres。
自定义格式备份的恢复则交给 pg_restore:
pg_restore -h 127.0.0.1 -U app -d appdb -j 4 -v appdb.dump
常用选项可归纳为几类:-d 指定目标库;-j 指定并行度;-c 在恢复前先 DROP 对象;--clean --if-exists 组合可避免对象不存在时报错;-n 按 schema 过滤;-t 按表过滤;-a 只恢复数据不建对象;-s 只恢复结构不导数据;-L 使用列表文件精确控制恢复哪些对象。这些选项决定了恢复的粒度与行为。
二、对象过滤与选择性恢复
生产环境中最常见的需求不是“全库恢复”,而是“只恢复某张表”或“只恢复某个 schema”。pg_restore 提供了多种过滤方式。-n public 只恢复 public schema;-t orders 只恢复 orders 表;-s 只恢复结构;-a 只恢复数据。需要注意的是,-t 过滤时,如果表有外键依赖,可能因依赖对象未恢复而失败,此时可配合 --disable-triggers(需超级用户)或先恢复结构再单独导数据。
更精细的控制方式是列表文件。先用 pg_restore -l appdb.dump > list.txt 导出对象清单,编辑后删除不需要的行,再用 pg_restore -L list.txt -d appdb appdb.dump 恢复。列表文件每行以分号开头的是注释,真正生效的是对象类型、schema、名称和 OID 字段。这种方式适合“恢复 90% 对象、排除少数问题表”的场景。
三、冲突处理与常见错误
恢复时最常见的冲突是“对象已存在”。典型报错:
ERROR: relation "orders" already exists
ERROR: role "app" does not exist
ERROR: permission denied for schema public
第一种情况可用 --clean --if-exists 先删除再重建,或改用 -c。第二种是角色缺失,需先在目标库创建对应角色,或使用 --no-owner 忽略属主设置。第三种是权限问题,通常因为执行恢复的用户不是超级用户,且目标 schema 的 CREATE 权限不足,可先用超级用户执行或调整授权。
另一个高频问题是 ON_ERROR_STOP 与 pg_restore 的差异:pg_restore 默认遇到错误会继续,最后以非零退出码汇总。因此恢复后必须检查退出码和日志中的 ERROR 数量,不能只看“命令跑完了”。
四、数据校验与结果判断
恢复完成后,至少要做三类校验:一是对象数量,对比源库与目标库的表、索引、序列数量;二是行数,对关键表执行 SELECT count(*) 与源库比对;三是抽样数据,检查主键、外键和关键字段是否完整。示例:
-- 源库与目标库分别执行
SELECT schemaname, relname, n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC
LIMIT 20;
若行数差异较大,需检查是否因并行恢复中断、过滤条件误删对象,或数据本身在导出后被修改。对于金额、库存等敏感字段,还应做聚合校验,例如 SUM(amount) 对比,避免“行数对但内容错”的隐蔽问题。
排查顺序建议:先看退出码与 ERROR 日志 → 再核对对象清单 → 再比对行数与聚合值 → 最后抽样验证业务字段。多数恢复失败都能在前两步定位。
注意:并行恢复 -j 只对数据加载和索引构建阶段有效,结构创建阶段仍是串行。并行度过高会加剧锁竞争和 IO 压力,建议从 2~4 起步,观察目标库负载后再调整。
掌握 psql 与 pg_restore 的分工、过滤选项、冲突处理和校验方法,才能把“备份能恢复”从口号变成可验证的能力。恢复不是终点,校验通过才是。