Windows 下 PostgreSQL 18 迁移到服务器:我用的 pg_dump + pg_restore
前几天把本地开发机上的一个 PostgreSQL 18 库挪到服务器上。两边都是 Windows,大版本一致,库不到 10G,业务也能接受停一会儿。本来想偷懒直接拷 data 目录,后来还是老老实实走了逻辑迁移。过程不复杂,但有几个地方容易卡住,记录一下。
先说结论:用 pg_dump 导出成自定义格式,拷到服务器,再用 pg_restore 恢复。目标库要提前建,角色最好也提前建,其他基本交给工具。
我这次的环境大概是这样:
- 本地:Windows + PostgreSQL 18
- 服务器:Windows + PostgreSQL 18
- 数据库大小:10G 以下
- 可接受停机
- 没有跨大版本,也没有跨操作系统
为什么不直接拷 data 目录
一开始确实想过,既然两边都是 Windows,大版本也一样,那把本地 PostgreSQL 的 data 目录复制过去不就完了?
后来想想还是算了。Windows 下直接拷 data 目录坑不少:服务账户权限、postgresql.conf 里的路径、pg_hba.conf、注册表里的服务配置,都可能对不上。运气好能启动,运气不好就是服务起不来,然后开始翻日志,排查成本反而更高。
逻辑迁移慢一点,但稳。尤其是库不大、又能停机的情况下,pg_dump / pg_restore 基本是最省心的方案。
迁移前先做几件事
首先确认版本。两边都是 PostgreSQL 18,工具直接用安装目录里的就行:
"C:\Program Files\PostgreSQL\18\bin\psql.exe" --version
然后停掉本地连这个库的应用,别再往里写数据了。pg_dump 虽然可以一边跑一边导,但为了保证快照一致,能停写就停写。
顺便看一下源库的编码和排序规则:
SELECT datname,
pg_encoding_to_char(encoding) AS encoding,
datcollate,
datctype
FROM pg_database
WHERE datname = 'old_db';
这个信息在服务器建库时最好保持一致。如果原库有特殊的 collate/ctype,目标库建得不一样,后面排序结果可能会有差异。我这次没什么特殊配置,所以直接用默认的。
服务器上先建一个空库:
"C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -h localhost -p 5432 -c "CREATE DATABASE new_db;"
如果原库用了自定义角色,比如 owner 不是 postgres,那最好先把角色也弄过去。不然恢复的时候会看到一堆 role does not exist。
只导出角色可以这样:
"C:\Program Files\PostgreSQL\18\bin\pg_dumpall.exe" -U postgres -h localhost -p 5432 -r -f "D:\backup\roles.sql"
拷到服务器后执行:
"C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -h localhost -p 5432 -f "D:\backup\roles.sql"
当然,也可以手动 CREATE ROLE,看哪个方便。
本地导出
导出命令我用的自定义格式:
"C:\Program Files\PostgreSQL\18\bin\pg_dump.exe" -U postgres -h localhost -p 5432 -d old_db -Fc -f "D:\backup\old_db.dump"
几个参数简单说一下:
-U postgres:数据库用户,换成你自己的-d old_db:源库名-Fc:自定义格式,单文件,自带压缩,恢复时比较灵活-f:导出文件路径
执行后会提示输入密码。如果想在脚本里免交互,可以用 PGPASSWORD 环境变量,但别把密码明文写在正式脚本里。
如果库特别大,想并行导出,可以用目录格式 -Fd 加 -j。不过 -Fc 不支持并行导出。我这次库不到 10G,没必要折腾,单文件反而好拷贝。
导出完看一眼文件大小,别是 0 字节。可以顺手算个哈希:
certutil -hashfile "D:\backup\old_db.dump" SHA256
拷到服务器后再对一下,防止传输过程中文件损坏。
传到服务器
这个就看实际情况了。远程桌面直接复制、局域网共享、U 盘都行。文件不大,怎么方便怎么来。
服务器恢复
目标库必须是提前建好的空库。如果里面已经有表,pg_restore 会报一堆 already exists。别直接在正式库上加 --clean,手滑容易出事。
恢复命令:
"C:\Program Files\PostgreSQL\18\bin\pg_restore.exe" -U postgres -h localhost -p 5432 -d new_db -v "D:\backup\old_db.dump"
-v 会输出详细过程,方便看日志。库不大就不用加 -j 了,加并行恢复虽然快一点,但日志会乱一些。
恢复过程中重点看错误。pg_restore 最后返回非 0 不一定代表全挂了,可能只是个别 owner 或权限警告,但日志还是要翻。常见的几类问题:
-
database does not exist
目标库没建,或者库名写错了。 -
role does not exist
原库的角色在服务器上没有。用pg_dumpall -r导角色,或者手动建。 -
extension "xxx" does not exist
原库用了扩展,目标服务器没装,或者当前用户权限不够。Windows 安装包一般带 contrib,但扩展还是要在目标库里CREATE EXTENSION。 -
schema already exists、table already exists
目标库不是空的。换个空库,或者先清理。
如果只是 owner 问题,实在不想建角色,也可以加:
--no-owner --no-privileges
但这样对象 owner 会变成执行恢复的用户,权限也丢了,后面还得补。生产环境不建议随便这么干。
恢复后别急着切应用
恢复完先连上去看看:
"C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -h localhost -p 5432 -d new_db
简单查几个东西:
SELECT count(*)
FROM information_schema.tables
WHERE table_schema = 'public';
表数量对一下,再抽几张大表 count(*),看看序列、视图、函数是不是都在。尤其是序列,别恢复完看着数据没问题,结果应用一插入就主键冲突。
然后跑一下统计信息:
"C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -h localhost -p 5432 -d new_db -c "VACUUM ANALYZE;"
pg_restore 之后统计信息可能不全,不跑一下,查询计划可能会比较难看。
最后再检查网络和认证配置。服务器防火墙要放行 5432,但别对公网开放,最好只给应用服务器 IP。pg_hba.conf 也要确认允许应用连接。Windows 下一般在:
C:\Program Files\PostgreSQL\18\data\pg_hba.conf
改完 reload 或重启服务。
应用连接串记得改:host、port、database、user、password。数据库迁完连不上,很多时候不是数据问题,是防火墙或者 pg_hba.conf 没配对。
几个小坑
- 目标库一定要先建,
pg_restore不会帮你建库。 - 角色最好先建,不然恢复日志里全是 owner 报错。
- 扩展要注意,目标服务器得装对应扩展。
- 编码和排序规则尽量和源库一致,建库时查清楚再建。
- 恢复日志要看完,别只看最后一行。
- 恢复完跑
VACUUM ANALYZE,再抽查数据。 - 迁移完成后,最好把服务器上的新库再备份一次。
我这次停机窗口留了一个小时,实际导出、拷贝、恢复、抽查,半小时左右就搞完了。库小确实省事。
如果两边都是 Windows、大版本一致、又能停机,pg_dump + pg_restore 基本就是最稳的路子。直接拷 data 目录不是不能玩,但除非你对 PostgreSQL 的目录结构、权限和服务配置都很熟,否则没必要给自己找麻烦。
本文来自博客园,作者:Y00,转载请注明原文链接:https://www.cnblogs.com/ayic/p/23119803
浙公网安备 33010602011771号