直接禁用 sh.stopBalancer() 即可,但需先确认迁移停止、元数据写入暂停,否则可能导致数据不一致;执行前须检查 balancer 状态、是否正在运行及是否存在进行中的迁移。

直接禁用 sh.stopBalancer() 就行,但必须确认迁移已停止、元数据写入已暂停,否则可能引发数据不一致。
执行 sh.stopBalancer() 前必须检查的三件事
这个命令本身不阻塞,但它只发信号;如果迁移正在进行,它会等迁移完成才真正停。所以你得先确认状态:
- 运行
sh.getBalancerState()—— 返回true表示开启,false表示已停(注意:返回false不代表迁移一定结束) - 运行
sh.isBalancerRunning()—— 这个更关键,返回true说明迁移线程仍在活动,此时调用sh.stopBalancer()会等待,但你得知道它在等什么 - 查
sh.status()或db.adminCommand({ "balancerStatus": 1 }),看输出里是否有"inBalancerRound": true或"migrationInProgress": true
sh.stopBalancer() 在 MongoDB 6.0.3+ 的行为变化
从 6.0.3 开始,自动分片拆分(auto-split)已被移除逻辑,sh.stopBalancer() 不再影响 splitChunk —— 因为它根本不会触发了。但均衡器本身仍控制 moveRange(基于集合大小而非 chunk 数量),所以禁用后:
- 不会再发生跨 shard 的数据迁移(
moveRange) - 也不会再合并 jumbo chunk(因为拆分已停用,合并也无意义)
- 但已有 jumbo chunk 仍可被读写,只是不会被自动处理
禁用后仍可能“看起来在动”的两个原因
你以为停了,但 sh.status() 显示 chunk 数在变?大概率是以下情况:
- 有应用正在执行
moveChunk或moveRange命令(比如手动触发或通过某些 ORM 隐式调用),这不受 Balancer 状态控制 - 配置服务器上存在未清理的
tags或zone ranges,导致某些写入路由异常,间接造成数据分布偏移(不是均衡器干的,但看起来像) - 你只在某个
mongos上执行了sh.stopBalancer(),而集群有多个mongos实例 —— 均衡器状态是全局的,但命令需在任一mongos上执行一次即可生效
真正“彻底”临时禁用的配套动作
仅靠 sh.stopBalancer() 不够保险,尤其在运维窗口期做关键操作(如备份、schema 变更、降级)时:
- 执行前务必确认没有进行中的
reshardCollection,否则sh.stopBalancer()可能被阻塞,且降级时会失败 - 如有必要,对关键集合单独禁用:
sh.disableBalancing("db.collection"),防止 Balancer 恢复后误操作 - 禁用期间避免任何元数据变更操作,例如
sh.addShard()、sh.removeShard()、sh.addTagRange()—— 这些操作依赖 Balancer 协调,强行执行可能卡住配置库
最常被忽略的一点:禁用 Balancer 后,getShardDistribution() 输出依然有效,但它的“不均衡”提示不再代表问题——那是你主动选择的状态。别把它当告警处理。


















