结论:分片集群迁移到云服务器不能仅靠mongodump+mongorestore,必须按组件逐个迁移,因该工具不导出分片元数据(如chunk分布、shard key路由规则、config server中的chunks表),导致恢复后mongos无法路由查询,出现空结果或“no chunks found”错误;且迁移前须停用负载均衡器、确保config server为wiredtiger副本集、各分片保留原replset名与oplog一致性。

直接说结论:分片集群迁移到云服务器,不能靠 mongodump + mongorestore 一导了之,必须按组件逐个迁移,且顺序和元数据一致性是核心风险点。
为什么不能直接用 mongodump/mongorestore 迁移分片集群
因为 mongodump 只导出集合数据,不包含分片元数据(如 chunk 分布、shard key 路由规则、config server 中的 chunks 和 databases 表)。恢复后,mongos 完全不知道数据该路由到哪,查询会返回空或报错 no chunks found for shard key。
常见错误现象包括:
-
db.collection.find()返回空结果,但db.collection.countDocuments({})显示有数据 -
sh.status()显示 chunk 数为 0 或分布异常 - 插入新文档时提示
write conflict或路由失败
必须先停用负载均衡器再操作
迁移过程中任何自动 chunk 迁移都会破坏源集群状态,导致目标端元数据混乱。连接任意一个 mongos 执行:
sh.stopbalancer()
确认已停用:
sh.getbalancerstate()
返回 false 才算生效。注意:sh.stopbalancer() 在 MongoDB 6.0.3+ 不再禁用自动 split,但必须确保迁移期间没有 chunk 拆分发生——所以实际操作中建议同时手动设置:
- 在所有 config server 上执行
db.settings.updateOne({ _id: "chunksize" }, { $set: { value: 1024 } })(强制大 chunk,减少拆分概率) - 检查
db.chunks.countDocuments({})在迁移前后是否一致
配置服务器(config server)迁移最易踩坑
自 MongoDB 3.4+,config server 必须是副本集(CSRS),且必须使用 wiredTiger 引擎。迁移时容易忽略三点:
- 新 config server 的
replSet名称必须与旧集群完全一致(比如configRepl),否则mongos无法识别 -
keyFile权限必须为600,且所有 config server 成员使用同一份文件 - 初始化副本集时,必须用
rs.initiate()后立即执行rs.add(),不能等所有节点启动完再批量添加——否则部分节点会因心跳超时进入STARTUP2状态卡住
验证 config server 是否就绪:
db.adminCommand({ listShards: 1 })
应返回所有分片信息;若报错 not master 或连接拒绝,说明 config 副本集未真正选举完成。
分片节点迁移要保留 replica set 名称和 oplog
每个 shard 是独立副本集,迁移时需保证:
- 新节点的
replSet名称与原集群完全一致(如shard1),否则mongos无法将其识别为合法分片 - 推荐用
rs.syncFrom()或直接复制dbpath(停机迁移),避免从零同步导致 oplog 断层 - 若用
mongodump导出单个 shard,必须加上--oplog和--oplogReplay,否则恢复后缺失写入历史,可能导致后续 chunk 迁移失败
迁移完成后,在新 shard 主节点上运行:
rs.printSecondaryReplicationInfo()
确认所有 secondary 的 optimeDate 与 primary 接近(差值
整个过程里最容易被忽略的是 config server 的 system.version 集合校验——它记录了集群版本号和分片拓扑快照。哪怕其他都对,只要这个集合时间戳或内容不一致,mongos 就会拒绝服务。迁移后务必比对新旧 config server 中该集合的 _id 和 lastMod 字段。











