搞数据库迁移这事,最怕的就是拍脑袋就干。我见过太多团队,上来就甩一句“把PostgreSQL从A库搬到B库”,结果迁移到一半发现数据对不上,业务停摆两小时,运维群里炸了锅。PostgreSQL迁移,说白了就是一场精心策划的手术——术前得做全面体检,术中得盯着生命体征,术后还得观察排异反应。别指望靠几个命令就能搞定,那跟闭着眼开车没区别。

第一步,得搞清楚你到底要迁移什么。很多人以为迁移就是“把表结构和数据倒过去”,但PostgreSQL远比想象中复杂。除了表、索引、视图这些基础对象,还有序列、触发器、存储过程、自定义类型、扩展插件——光一个扩展就能让你折腾半天。我有个朋友,迁移时漏了扩展,结果所有默认值为的列全部报错,生产环境直接瘫痪。所以,迁移前必须做一次完整的对象清单扫描,用导出所有DDL,然后逐项核对。别偷懒,这一步省下的时间,后面会加倍还回来。
说到迁移工具,很多人第一个想到的就是和。这对组合确实经典,但有个致命缺陷:在数据量超过100GB时,单线程的导出导入速度会让你怀疑人生。我见过一个案例,用迁移200GB数据,跑了整整18个小时,业务方差点把运维同学的工位给砸了。这时候就得考虑并行方案:配合参数可以并行导出多个表,同样支持并行导入。更狠一点的,用这个工具,它能自动并行迁移整个集群,包括所有对象和数据,速度能快3到5倍。不过要注意,并行方案对源库和目标库的CPU、内存和网络带宽都有要求,别还没迁移完,先把源库压垮了。
数据一致性,是迁移过程中最让人头秃的问题。你辛辛苦苦导完数据,正打算切流量,突然发现源库还在写数据——这就尴尬了。更隐蔽的问题是,那些没有主键的表,在并行迁移时可能会造成重复数据。我见过一个团队迁移订单表,因为表里没有唯一索引,并行迁移时丢了几十万条记录,靠业务日志才补回来。所以,迁移前一定要给所有大表加上主键或唯一约束,实在加不了的,就用的排除掉,单独用命令配合事务处理。另外,增量同步也是个好办法,用或这类工具,先全量迁移,再实时同步增量数据,在业务低峰期做一次短时间停机切换。我通常建议客户给停机窗口留出30分钟,但实际上熟练操作后,5到10分钟就能搞定。
网络和带宽问题,经常被低估。很多人觉得“内网迁移,带宽肯定够”,结果一跑起来发现,源库和目标库之间隔了三层防火墙,每秒只能传几MB。更夸张的是,有个团队把目标库建在另一个城市,延迟高达50毫秒,迁移一个10GB的表居然花了4个小时。解决办法有两个:一是压缩传输,加上参数,能减少50%到70%的数据量;二是用做物理迁移,它直接复制数据文件,比逻辑迁移快得多。但物理迁移有个前提:源库和目标库的操作系统、PostgreSQL版本、甚至编译选项都要一致,否则容易出兼容性问题。
迁移完数据,千万别急着切流量。第一步,先跑一遍数据校验。我习惯用对比源库和目标库的行数,再用扩展检查表的实际大小。更严谨的做法是,随机抽取10%的表的全量数据,用函数算哈希值对比。有个客户就是因为漏了这一步,结果发现某个大表的索引迁移后完全损坏,导致查询性能暴跌。第二步,跑一遍核心业务的查询语句,看看执行计划和性能是否一致。PostgreSQL的查询优化器在不同版本间行为有差异,同样的SQL在12版和15版上可能走不同的索引,导致响应时间从10毫秒飙到10秒。
业务切换那一刻,最考验的是心理素质。我见过最淡定的运维,提前准备好了回滚脚本,切流量前在源库和目标库之间搭了双向同步,一旦发现问题,30秒内就能切回源库。但大多数人没这个条件,那就得靠“灰度切换”来降低风险:先切一小部分只读流量到新库,观察半小时,确认没问题后再切写流量。有个细节容易被忽略——应用层的连接池。很多应用用了或做连接池,迁移后连接池里的缓存还指向旧库,导致新库空转。所以,迁移前一定要让应用重启连接池,或者手动清空缓存。
说几句掏心窝的话。PostgreSQL迁移这东西,技术难度其实不大,真正难的是“人”的问题——业务方不理解为什么要停机,领导催着要上线,运维同学自己心里也没底。我建议每个做迁移的团队,都准备一份“事故预案”:如果数据对不上怎么办?如果性能比原来差怎么办?如果迁移中断了怎么办?把这些问题想清楚,比背一百个命令都管用。毕竟,数据库迁移成功了没人夸你,但搞砸了所有人都会记得你。记住,慢就是快,稳就是赢。


