干这行十年,最怕听到的一句话就是“帮我把数据库迁一下”。听起来轻飘飘的,背后全是坑:表结构不一致、字符集乱码、外键约束断链、数据量大到导出文件几个G,传到一半网络抽风,前功尽弃。更别提那些分布在十几个业务系统里的库,一个库一个版本,一个库一套密码,手动操作能把你熬成熊猫眼。所以后来我养成了个习惯,凡是重复超过三次的活,一定写脚本或者找工具,把“手动”变成“自动”。今天聊的批量迁移,就是把我踩过的坑、试过的招儿,掰开揉碎讲给你听。

先说最基础也最容易被忽略的一步:盘点。很多人上来就写迁移脚本,结果跑一半发现源库里有张表叫“user”,目标库里也有,但字段顺序完全不一样,数据灌进去直接错位。我的做法是先做一次全量摸底,用一条SQL把每个库的表数量、行数、占用空间、修改时间全查出来,存成一个清单文件。这一步花不了十分钟,但能让你在真正动手前心里有数:哪些表是核心业务表,哪些是日志表可以延迟迁移,哪些表干脆就是死数据不用管。批量迁移最怕的就是“一视同仁”,全量灌进去,出了问题都不知道从哪查起。
盘点完,接下来是选工具。市面上工具不少,但真到批量场景,我建议优先考虑命令行工具,比如mysqldump、pg_dump这类原生自带的,它们稳定、文档全,而且支持流式输出,不会像GUI工具那样导个大库就卡死。如果你要跨数据库类型迁移,比如从MySQL搬到PostgreSQL,那就要用中间格式过渡,先导成CSV或者SQL通用格式,再做类型映射。这里有个细节:导出时一定要加上“--single-transaction”和“--quick”参数,前者保证一致性快照,后者避免一次性加载到内存里把机器搞挂。批量操作时,写个for循环套上这些参数,一次跑十几个库,比手动一个个敲命令省太多事。
当然,光靠自带工具还不够,真正提升效率的是并行和断点续传。我见过有人写脚本串行跑迁移,一个库要半小时,十几个库就是七八个小时,中间任何一个库失败,后面的全白等。我的做法是分两步走:第一步,用GNU parallel或者简单的xargs -P参数,把多个库的导出任务并行执行,比如同时跑四个导出,充分利用多核CPU和磁盘IO;第二步,大表单独处理,按主键范围或者时间范围切片,每片一个文件,传到目标库后再分批导入。这样即使中途断了,只需要重跑失败的那一片,而不是整个库重新来一遍。这个思路听起来简单,但真能帮你省下好几个通宵。
说到跨机房的批量迁移,还有个隐形杀手:网络带宽。我吃过一次亏,一个库导出来2.3G,结果传输链路只有10M带宽,跑了快一个小时,中间还断了一次。后来我养成了压缩传输的习惯,导出后直接管道接上gzip,再传到目标端解压导入。压缩率对文本型数据特别友好,2.3G能压到400M左右,时间直接缩到原来的五分之一。如果你用的是rsync或者scp,记得加上压缩参数,比如scp的-C选项。另外,大文件传输建议用rsync的断点续传功能,比scp稳得多,网络抖动也不怕,断了接着传,不用从头再来。
批量迁移里最让人头疼的其实是数据一致性校验。很多人迁移完就完事了,觉得导入成功就等于数据对了,结果业务上线第二天发现某个字段全空了。我的习惯是迁移完成后,一定要跑一遍校验脚本:两边分别统计每张表的行数、关键字段的SUM值、MAX/MIN值,然后做个对比。写个简单的shell脚本,循环比对,有差异的自动标红打日志。不要嫌麻烦,这一步能帮你拦住90%的隐性错误。尤其要注意自增主键的边界值,目标库如果已有数据,新导入的数据自增ID可能会冲突,提前把自增值调好,能省掉后面一堆麻烦。
还有一类特殊情况,就是存量数据加上增量数据的迁移。如果你没法停机,或者停机窗口只有半小时,那就要用“全量+增量”的双轨策略:先做一次全量导出导入,同时开启binlog或者WAL日志记录增量变更,等全量迁移完成后,再把增量日志重放到目标库,做一次短暂的只读切换。这个操作稍微复杂点,但熟练之后你会发现,它比直接停机迁移要优雅得多,业务影响面小,风险也可控。批量场景下,每个库都按这个流程走,只是把切换动作统一放到同一时间窗口,减少业务侧的感知。
说个容易被忽略的点:迁移完之后的验证不能只看数据,还要看权限、存储过程、触发器、定时任务这些“软配置”。我见过不少案例,数据全过去了,但存储过程里引用了旧库名,一调用直接报错。批量迁移时,把这些对象一并导出,写个脚本批量替换库名和连接串,再统一部署到目标环境。还有权限账号,要提前生成授权语句,批量执行,别等业务方找上门说连不上库,才发现漏了授权。这些细节看着琐碎,但正是它们决定了迁移这件事是“完成”还是“真正搞定”。
批量迁移这事,说到底就是一场工程化思维和手忙脚乱的较量。把每一步都脚本化、可重复、可验证,你就能从“救火队员”变成“幕后导演”。我现在的习惯是,所有迁移脚本都存到版本库里,参数化配置,下次遇到类似需求直接复用,改改库名和连接信息就能跑。这套流程帮我在很多项目里做到“一键搞定”,虽然中间依然会有意外,但至少我有底——脚本跑完,日志清晰,校验通过,我敢拍胸脯说数据没问题。


