数据库搬家这件事,干过的人都懂,表面上就是“把数据从A点挪到B点”,可真操作起来,从版本兼容性到字符集编码,从索引失效到序列错乱,每一步都可能踩雷。PostgreSQL作为开源数据库里的老牌劲旅,迁移方案多得让人眼花缭乱,但方案多不等于选择就简单。有人图省事直接pgdump一把梭,结果数据量上了T级别,恢复时等得花儿都谢了;有人迷信逻辑复制,结果碰上大事务或者DDL变更,延迟高得让人怀疑人生。说到底,迁移不是“复制粘贴”那么天真,它考验的是你对数据形态、业务容忍度和工具链的深度理解。

先聊聊最基础的逻辑备份。pgdump和pgdumpall这对组合拳,几乎是每个PostgreSQL DBA的入门必修课。pgdump适合单库或指定表的导出,生成的是SQL脚本或自定义格式文件,恢复时用psql或者pgrestore就能搞定。这套方案最大的优点是简单直观,跨版本迁移时兼容性也相对友好,比如从PG 11迁到PG 15,只要语法不涉及废弃特性,基本都能顺利过关。但缺点同样扎眼——它走的是“导出再导入”的路径,数据量一旦超过几十GB,导出耗时、传输耗时、导入耗时三者叠加,整个窗口期长得让人焦虑。更要命的是,逻辑备份只备份数据本身,不包含索引的物理结构,恢复后索引需要重建,大表上重建索引的时间往往比导入数据还长。
物理备份是另一条路,pgbasebackup就是典型代表。它直接拷贝数据目录的文件,生成一个和源库完全一致的副本,包括所有事务日志和配置文件。恢复时只需要把备份目录放到新实例上,启动即可,速度比逻辑备份快好几个量级。而且,物理备份天然支持时间点恢复(PITR),配合WAL归档,可以把数据库恢复到任意一个时间点,这对生产环境来说简直是救命稻草。但物理备份也不是没有代价——它要求源库和目标库的版本、平台、甚至编译选项都得高度一致,跨大版本迁移时基本行不通。而且,备份文件体积通常比逻辑备份大不少,传输和存储成本得提前算清楚。
如果你追求“不停机迁移”,逻辑复制和流复制就是绕不开的话题。逻辑复制从PG 10开始成为内置功能,基于发布/订阅模型,可以精准选择需要复制的表,还能跨大版本工作——比如PG 12发布,PG 15订阅,这在某些升级场景里非常实用。流复制则更底层,直接传输WAL日志,延迟极低,几乎可以做到秒级同步,但要求主备版本完全一致,而且只能复制整个实例,没法挑表。实际操作中,很多人会用流复制先做物理同步,等业务低峰期再切换,或者用逻辑复制做渐进式迁移,先同步数据,再平滑切换应用连接。两种方式各有适用场景,关键看你能否接受切换窗口内的短暂只读状态。
工具选型这事儿,说复杂也复杂,说简单也简单。官方工具里,pgdump、pgrestore、pgbasebackup是老三样,稳定可靠但操作繁琐。开源社区里,pgloader是个好帮手,它不仅能从MySQL、SQLite等异构数据库迁移到PostgreSQL,还能处理同构迁移时的类型转换和默认值映射,省掉不少手工改SQL的功夫。商业工具就更省心了,像AWS DMS、Azure Database Migration Service这类云厂商服务,界面化操作,点几下手表就能同步,但价格不菲,而且绑定特定云平台,后续想再迁走就麻烦。我的建议是,小数据量、一次性迁移,用pgdump足够;大数据量、跨版本、持续同步,优先考虑逻辑复制或pgloader;追求极简运维,再考虑商业服务。
迁移过程中有个细节特别容易被忽视——序列。PostgreSQL里序列是独立对象,逻辑备份导出的序列值往往和实际数据不一致,恢复后可能出现主键冲突。我见过不止一次,数据导入成功,应用一启动就报duplicate key,查了半天发现是序列没跟上。解决的办法也不复杂,如果用的是pgdump的默认格式,它会附带序列的当前值,但如果你只导了数据表忘了序列,那就得手动重置:SELECT setval('yoursequence', (SELECT MAX(id) FROM yourtable)); 这种坑,不踩一次真的记不住。
另一个高频问题出在扩展和插件上。有些业务用了PostGIS、pgtrgm这类扩展,迁移到新环境后,扩展没装或者版本不一致,查询直接报错。我建议迁移前先跑一遍SELECT * FROM pg_extension; 把依赖的扩展列出来,到目标环境提前安装好对应版本。还有一点,自定义数据类型、函数、触发器,这些对象在逻辑备份时都会被导出,但恢复顺序有讲究——函数可能依赖类型,类型可能依赖表,表可能依赖扩展,顺序错了就报错。稳妥的做法是分步恢复,先扩展,再类型,再表结构,数据,别指望一条命令搞定所有。
说到实战案例,我去年帮一个客户做过一次从阿里云RDS PostgreSQL迁移到自建机房的活儿。数据量大概2TB,业务要求切换窗口不超过30分钟。我们用了逻辑复制做增量同步,提前一周搭建好订阅关系,每天监控延迟。切换当天,先停写应用,等延迟归零,然后切换数据库连接,整个过程用了不到15分钟。但前置准备工作做了整整一周——包括表结构对比、权限梳理、序列同步、甚至应用层连接池的超时参数调整。迁移这事儿,功夫全在事前的细致排查,真到了切换那一步,反而是最轻松的。
回到迁移的本质。数据搬过去只是第一步,搬完之后验证才是重头戏。行数对比、抽样查询、关键业务链路演练,一样都不能少。很多人觉得迁移完就万事大吉,结果第二天业务高峰期才发现某个索引没建、某个分区表策略不对,那时候再补救,代价可就大了。PostgreSQL迁移没有银弹,每个方案都有取舍,关键是根据业务容忍度、数据规模、团队技术储备去做权衡。数据是命根子,迁移是技术活,也是责任心活——多花时间在规划上,少在切换时手忙脚乱,这才是老司机的做事方式。


