pg_dump -h host -U postgres -d shop -Fc -f shop.dump 生成压缩的转储,pg_restore -d shop_copy shop.dump 再把它放回去。但在这一切之前,客户端必须不比服务器旧:较老的 pg_dump 会直接拒绝,而这一个错误正是备份始终没做成的最常见原因。
1. 卡住一切的那个错误
$ clai 从 pg17 服务器上导出 shop 数据库→ pg_dump -h pg17 -U postgres -d shoppg_dump: error: aborting because of server version mismatchpg_dump: detail: server version: 17.10; pg_dump version: 16.14 (Debian 16.14-1.pgdg13+1)
没有哪个参数能绕开它。你需要对应版本的客户端——postgresql-client-17 包,或者干脆用和服务器相同的容器镜像。反过来是没问题的:较新的客户端导出较旧的服务器毫无怨言。
2. 用 custom 格式,而不是 .sql
$ clai 把 shop 数据库导出成二进制文件→ pg_dump -h pg17 -U postgres -d shop -Fc -f shop.dump
-Fc 写出的是压缩归档,pg_restore 可以从中按需取用,还能用 -j 并行导入。普通 .sql 两样都做不到——它只能整份、按顺序灌进 psql。
3. 恢复之前先看看里面
$ clai 显示转储文件里有什么→ pg_restore -l shop.dump218; 1259 16386 TABLE public orders postgres217; 1259 16385 SEQUENCE public orders_id_seq postgres3427; 0 0 SEQUENCE OWNED BY public orders_id_seq postgres3271; 2604 16389 DEFAULT public orders id postgres3420; 0 16386 TABLE DATA public orders postgres
这就是归档的目录。把它存成文件,删掉不需要的行,再用 -L 交回去——正经的选择性恢复就是这么做的。
4. 恢复到另一个数据库
$ clai 把转储恢复到 shop_copy 数据库→ pg_restore -h pg17 -U postgres -d shop_copy shop.dump
数据库必须事先存在——createdb shop_copy——因为不加 -C 的 pg_restore 不会创建它。成功时这条命令一个字也不说,所以用 select count(*) 去核对。
5. 只要一张表,只要数据
$ clai 只导出 orders 表,不要表结构→ pg_dump -h pg17 -U postgres -d shop -t orders --data-only -f orders-data.sql
-t 把范围缩到一个对象,--data-only 去掉 CREATE TABLE。当目标库里已有同样结构的表、只缺数据时很好用。
6. 往非空数据库上恢复
$ clai 在已有数据库上覆盖恢复这个转储→ pg_restore -h pg17 -U postgres -d shop_copy --clean --if-exists shop.dump
不加 --clean 时,同一份转储第二次就会失败:pg_restore: error: could not execute query: ERROR: relation "orders" already exists。--clean 会在重建前删除对象,--if-exists 则让那些还不存在的对象不再报错。
Gotchas
- 旧客户端根本导不了新服务器。 已验证:pg_dump 16.14 面对 17.10 的服务器立刻停止。让客户端不比服务器旧;在容器环境里,最省事的办法就是用服务器同款镜像跑 pg_dump。
pg_restore -t是追加,不是替换。 把一张表恢复进已经有数据的库,会得到ERROR: duplicate key value violates unique constraint "orders_pkey"。先 truncate,再 restore。pg_restore出错后仍返回 0。 已验证:键冲突时它打印了错误,退出码依旧是 0。脚本里要加--exit-on-error,否则坏掉的恢复看上去像是成功。
Related questions
怎么只导出表结构? pg_dump --schema-only 只给结构不给数据,--data-only 则相反。
.sql 转储用什么恢复? psql -d 库名 -f dump.sql。pg_restore 只认 -Fc、-Fd 和 -Ft 三种格式,纯文本不在其中。
大库恢复怎么加速? pg_restore -j 4 会并行导入数据并建索引,仅适用于 custom 和 directory 格式。
See also
CliAI 会用适合当前任务的参数写出导出与恢复命令,并在它们碰到数据库之前先显示出来。一行安装。