数据库迁移这事儿,干过的都知道,跟搬家似的,看着简单,一上手全是坑。MongoDB迁移更是其中一门手艺活,没点经验,真敢上手就是给自己找罪受。我前阵子帮朋友公司搞了个 MongoDB 从 3.6 升级到 5.0 的迁移,中间踩的雷够写一本书了。最让人头大的不是 export‑import 那点事儿,而是数据一致性。生产环境有几十亿条数据,根本停不下来,只能在线迁移。这时候就得祭出 MongoDB 自带的复制集机制:先搭建一个从节点,让它追上主节点的数据,再手动切主。听起来简单?从节点追数据时,如果主节点写压力太大,oplog 不够用,从节点就会掉队。我那次就是没算好 oplog 大小,结果从节点卡了大半天,只能扩容 oplog 重新同步。

具体到操作细节,迁移前必须做好几件事。第一件是评估数据量,别光看文档里的数字,要实际跑一下 ,看看集合大小、索引大小、存储引擎占用。MongoDB 的 WiredTiger 存储引擎有压缩,磁盘上的数据和内存里的数据量差别很大,迁移时带宽和时间的估算要按未压缩的量来。第二件是检查索引,老项目里常常堆了十几个无用索引,迁移过去全重新建一遍,时间翻倍不说,还占磁盘。我见过最夸张的案例:一个集合 500 GB 数据,索引占了 300 GB,迁移时重建索引跑了三天三夜。第三件是网络环境,跨机房迁移最怕丢包和高延迟,带宽不足就开启压缩。 支持 参数,能省一半流量,但会多消耗 CPU,需要权衡。
再说迁移工具的选择。/ 这对组合适合小规模数据,几十 GB 以内,表结构简单、没有分片。但数据量上到 TB 级别,这俩就力不从心,恢复时单线程写,慢得让人崩溃。这时候可以使用 MongoDB 的复制集同步机制,或者第三方工具如 mongo‑migrate。复制集迁移的好处是增量同步,只要 oplog 足够大,几乎能做到零停机。但有个致命问题:如果源库是单节点、不是复制集,就没法直接搭建从节点。我处理过这种情况,需要先在源库配一个隐藏从节点,等数据同步完再把它升级为新的主节点,并修改应用的连接串。每一步都要小心,尤其是改连接串时,应用端的连接池如果不刷新,旧的连接断掉后新请求可能打到空节点,直接报错。
迁移过程中最怕数据不一致。MongoDB 是 schema‑free 的,同一个集合里字段类型可能不一样。我遇到过用户 ID 字段,有的文档是字符串,有的是数字,迁移过去后查询就出问题了。还有 字段,默认是 ObjectId,但有些应用自己生成字符串 ,迁移时如果不注意,插入新库会报主键冲突。更坑的是数组字段,MongoDB 支持嵌套数组和对象, 导出时是 BSON 格式,但 导入时如果版本不一致,低版本不认识高版本的新类型(比如 Decimal128),会直接报错。所以迁移前最好在测试环境跑一遍完整流程,用生产数据的子集验证所有字段类型和查询都能正常。
还有一个容易被忽略的点——分片集群的迁移。MongoDB 的分片集群结构复杂,包含 config server、mongos 和 shard 节点,迁移时不能简单把所有 shard dump 再恢复。分片键的元数据保存在 config server 里,迁移后元数据不匹配,数据就会散架。我朋友公司就吃过这亏:他们用 导出了所有 shard 的数据,然后在目标集群上恢复,结果查询时发现有些分片的数据落到了别的 shard,路由全错。正确做法是先备份 config server 的元数据,再逐个 shard 迁移,使用 重新平衡数据。或者直接搭建一个目标分片集群,把源集群的节点一个个加入新集群,等数据同步完再切换。这整个过程对运维要求极高,每一步都要监控复制延迟和集群状态。
迁移后的验证环节,很多人觉得数据能查出来就完事了,实际上远远不够。我一般会做三步验证:第一步,对比文档数,用 ,但在分片集群下要注意它可能不准,最好用聚合管道统计。第二步,随机抽样,写脚本从源库和目标库分别取同一 的文档,逐字段对比,包括嵌套字段和数组顺序。我曾发现数组顺序不一致的问题,原因是 MongoDB 的存储引擎不保证文档内部顺序,而应用层可能依赖顺序,这就埋雷了。第三步,压测,使用真实查询负载跑一遍,观察响应时间、慢查询和连接数。有一次迁移后所有查询都变慢,排查发现目标库的索引统计信息没有更新,执行计划走了全表扫描。重新运行 (或 )更新统计后,性能恢复正常。
说说备份和回滚方案。迁移前必须做全量备份,但不能只备份数据,还要备份配置文件、认证信息和监控脚本。我曾遇到一次,迁移到一半目标库磁盘满了,想回滚却发现源库的备份文件在传输过程中被截断,只能从其他副本恢复,耽误了好几天。所以备份文件要放在独立存储上,最好使用快照或 S3 等对象存储,并保留至少两份不同的备份。回滚时还有个坑:迁移过程中如果源库还有写操作,回滚后这些数据会丢失。解决办法是迁移期间把源库设为只读,或者使用延迟复制集保留一段时间的增量数据。无论如何,都要和业务方提前沟通停机窗口,别擅自改库状态。
数据迁移这事儿,说到底是对细节的把控。MongoDB 本身很强大,但它的灵活性也意味着迁移时容易踩坑。从 oplog 大小到字段类型,从网络带宽到索引重建,每个环节都可能出问题。我的经验是,别盲目相信任何自动化工具,每一步都要手动验证、每个参数都要确认。迁移完成后,别急着删源库,至少保留一周,等业务跑稳了再考虑清理。毕竟数据是公司的命根子,一次迁移失误,可能就是灾难。


