mongorestore不能直接用于分片集群迁移,因其默认直连单分片写入,导致数据分布倾斜、查询路由失效;必须提前启用分片、创建分片集合,并使用--noTableScan参数确保通过mongos路由写入。

分片集群间迁移存量数据,不能靠 mongodump + mongorestore 直接全量灌入新集群——它会绕过分片逻辑,所有数据默认写进一个分片,彻底破坏数据分布和查询性能。
为什么 mongorestore 不能直接用于分片集群迁移
这是最容易踩的坑。当你对目标分片集群执行 mongorestore,即使连接的是 mongos,只要没显式启用分片行为(比如没提前创建带分片键的集合),工具默认以“直连单个分片”的方式写入,结果是:
- 所有文档都落在同一个分片上,
sh.status()显示块(chunk)严重倾斜 - 查询路由失效,大量请求被转发到同一节点,CPU 和磁盘 I/O 爆满
- 后续手动触发
sh.splitAt()或sh.moveChunk()效率极低,且可能因锁竞争失败
必须提前在目标集群完成分片初始化
迁移前,目标集群必须已正确配置分片键、启用分片,并预建好空集合。否则任何导入操作都会退化为单分片写入。
- 先用
sh.enableSharding("db_name")启用数据库分片 - 再用
sh.shardCollection("db_name.coll_name", { "shard_key": 1 })创建分片集合 —— 注意:分片键必须与源集群一致,且字段类型、索引存在 - 确认分片状态:
sh.status()中该集合的chunks数量应 > 0,且分布在多个分片上 - 如果源集合已有大量数据,建议先在源集群执行
sh.splitAt()均匀切分,再迁移,避免目标端首次均衡压力过大
推荐用 mongodump + mongorestore --noTableScan 组合
--noTableScan 是关键开关,它强制 mongorestore 尊重分片元数据,通过 mongos 路由写入,而不是直连分片节点。
- 导出时加
--oplog获取变更点,便于后续增量同步 - 恢复命令示例:
mongorestore --host mongos_host:27017 --username admin --authenticationDatabase admin --noTableScan /backup/20260721 - 务必省略
--drop参数 —— 它会删掉已分片的集合结构,导致重新变成非分片集合 - 若遇到
writeConcern error,检查目标分片副本集 writeConcern 配置是否匹配(如w: "majority"在小副本集里可能不满足)
超大数据量(TB+)建议走物理复制或 chunk 迁移
当数据量超过几 TB,网络带宽和 mongorestore 单线程瓶颈明显,此时应放弃逻辑导出导入路径。
- 停写窗口允许时:直接 rsync
data/db目录到新分片节点,再修改mongod.conf中sharding.clusterRole: shardsvr并重启 - 不停服场景:用
sh.moveChunk()手动调度块迁移,配合sh.disableBalancing()控制节奏,但需注意 chunk 大小(默认 64MB)和迁移并发限制 - 跨云或异构环境:考虑 MongoDB Atlas 的
Online Migrator或第三方工具如Relational Migrator,它们封装了 chunk 级校验与重试逻辑
真正麻烦的不是数据搬过去,而是让新集群“认得清”每一块数据该在哪、怎么路由。分片键定义、config server 同步状态、balancer 开关时机,这三个点任何一个没对齐,迁移后就会出现查得到但慢得离谱,或者根本查不到的情况。

















