前两天有个朋友找我吐槽,说他们公司的数据库迁移搞砸了。本来计划周末两天搞定,结果从周五晚上干到周一早上,业务停了整整一个周末,老板气得差点拍桌子。我问他用的什么数据库,他说MongoDB。我说这不稀奇,MongoDB迁移翻车的案例我见得太多了,问题往往不是工具不行,而是人太急。很多人一上来就想用工具“一把梭”,结果数据丢了、业务断了、回滚又回不去,只能硬着头皮重新来。其实MongoDB的数据迁移没那么玄乎,关键是要搞清楚几个核心点:数据量、业务容忍度、网络环境,还有你最想保住的东西是什么。今天我就把这些年踩过的坑、涨过的记性,掰开揉碎地跟你聊聊。

先说最常见的坑:直接用mongodump和mongorestore。这两个工具是MongoDB自带的,看起来简洁高效,但很多人用起来就出问题。我见过一个团队,数据库有200 GB左右,直接用mongodump全量导出,结果跑了十个小时,导出期间业务还在写数据,导出来的数据本身就是不一致的。更惨的是,他们后来用mongorestore导入到新库,发现某些集合的索引没建对,某些文档的 id 重复了,只能手动补数据。为什么会这样?因为mongodump默认不带 --oplog 参数,导出的只是某个时间点的快照,而不是一个连续的数据流。如果业务持续写入,你导出来的数据就是“脏”的,前后不一致。正确的做法是加 --oplog 选项,这样导出的数据会包含 oplog 日志,还原时可以重放这段时间内的写入操作,保证数据最终一致。但即使这样,如果数据量上 TB,或者网络带宽有限,这种方式效率极低,基本属于“能用但别指望快”的方案。
再来说说增量迁移。很多业务不允许长时间停机,那就要考虑增量同步。MongoDB 本身没有像 MySQL 那样成熟的 binlog 解析工具,但可以通过复制集(Replica Set)的 oplog 来实现。思路是:先把新库配成旧库的从节点,让它通过复制集机制实时同步数据,等两边数据追平后,再切主节点,完成迁移。这个方案看起来很完美,但实际操作中坑也不少。比如,如果旧库的 oplog retention 设置太短,新库同步速度跟不上,追到一半发现 oplog 已经被覆盖,整个复制链路就断了,只能重新全量同步。而且,MongoDB 复制集对网络延迟很敏感,如果旧库和新库不在同一个机房,或者跨地域部署,延迟一高,同步速度会非常慢,甚至频繁断连。我的稳妥做法是:先评估 oplog 窗口大小,至少保证能覆盖全量同步加增量追赶的时间;如果不够,手动调大 oplog 大小;同时,用 rs.status() 和 rs.printReplicationInfo() 持续监控同步状态,别等出了问题再补救。
还有一种场景是跨版本迁移,比如从 3.6 升到 5.0,或者从 4.0 升到 7.0。大版本升级往往伴随存储引擎、索引结构、认证方式的改动,直接迁移很容易翻车。我有个客户,从 4.0 升到 6.0,直接用 mongorestore 把数据倒进去,结果发现新版本的 WiredTiger 引擎对某些字段类型的处理方式变了,原本能正常查询的字段在新版本里变成了非法值,导致应用报错。更麻烦的是,MongoDB 4.0 之后默认开启了新的认证机制 SCRAM‑SHA‑256,旧版本的用户密码格式不兼容,迁移后所有用户都无法登录。正确的做法是走官方推荐的滚动升级路径:先升级到中间版本(比如 4.0 → 4.2 → 4.4 → 5.0 → 6.0),每一步都测试兼容性,确认没问题再继续。虽然慢,但稳。如果业务等不了,也可以用 mongosync 这种专门做跨版本同步的工具,但前提是先搭建好测试环境,跑一遍全流程,确认所有功能都正常再上生产。
说到工具,社区里还有几个常用的,比如 mongoimport / mongoexport,适合小批量数据导入导出;还有第三方工具如 Studio 3T、Robo 3T 集成的迁移功能,图形化操作,适合非技术人员。但我要泼一盆冷水:这些工具大多只适合百 GB 级别的数据,或者做临时性迁移。一旦数据量上 TB,或者对一致性要求高,工具本身的性能和稳定性就成了瓶颈。我见过有人用 mongoexport 导出一个 10 GB 的集合,结果因为内存不足直接卡死;也有人用 Studio 3T 做迁移,跑到一半连接断了,没有断点续传功能,只能从头再来。所以,选择工具之前,先弄清楚你的数据规模、网络条件、业务容忍度。如果数据量在 100 GB 以内,网络带宽够,业务可以停机几小时,那 mongodump + mongorestore 就够了;如果数据量在 TB 级别,或者业务不能停机,就要考虑复制集或专业的数据同步工具,比如 MongoDB Atlas 的 Live Migration,或者第三方产品如 Striim、Arcion。
数据校验是很多人忽略的一步,却是最容易出问题的环节。迁移完成后,你怎么知道数据有没有丢、有没有错?很多人只检查总数,发现文档数对得上就觉得没问题。但 MongoDB 的文档结构复杂,可能某些嵌套字段、数组顺序、数据类型发生了变化,总数相同不代表内容一致。我的建议至少做三件事:第一,用聚合框架统计每个集合的文档数、字段数、索引数量,和旧库对比;第二,随机抽取几个集合,使用 find().sort({id:1}).limit(1000) 导出样本数据,人工比对关键字段;第三,跑一遍应用的核心业务流程,看看业务逻辑有没有异常。如果条件允许,可以用 MongoDB Compass 或第三方工具做全量校验,比如比较每个文档的 hash 值,虽然费时,但适合数据量不大的场景。最稳妥的方案是在迁移前就写好校验脚本,迁移后“一键”执行,别等业务报错了才回头排查。
说一个心法:永远给自己留条后路。我见过太多人迁移完就把旧库删了,结果新库出问题,回滚无门。正确的做法是保留旧库至少一周,等新库运行稳定再清理。如果条件允许,最好做一次数据库快照或备份,再放在不同的存储上。迁移过程中,每一步都要有明确的回滚方案:比如全量导出阶段,如果导出失败,是重试还是换方案?增量同步阶段,如果同步延迟超过阈值,是暂停写入还是先切回旧库?这些细节提前想清楚,真出了问题才不会慌。另外,建议在迁移前做一次完整的灾难演练,模拟网络中断、磁盘满、同步失败、认证错误等异常场景,确保团队每个人都知道该怎么响应。别等到周末晚上出事了才打电话找人,那时候谁都不想接。
MongoDB 数据迁移这件事,说难不难,说简单也不简单。工具和方法都摆在那里,但真正决定成败的是你对数据的敬畏心和对细节的把控。别想着一步到位,别迷信某个工具能解决所有问题,更别在关键时刻才发现自己没留后路。数据是业务的生命线,迁移就是给生命线做手术,容不得半点马虎。


