sh.stopbalancer() 必须在mongos上执行,因sh是mongosh注入mongos的全局对象;停用前需确认无movechunk操作,启用后须验证sh.isbalancerrunning()为true且sh.status()显示迁移正常。

sh.stopBalancer() 必须在 mongos 上执行,否则报错
直接连到 mongod(比如 shard 或 config server)里调用 sh.stopBalancer() 会立刻失败,错误类似 sh is not defined 或 not authorized on admin to execute command。因为 sh 是 mongosh 在 mongos 上注入的全局对象,只在 mongos 进程中可用。
实操建议:
- 先确认连接目标:用
mongo --host <mongos-host>:27017</mongos-host>或mongosh "mongodb://<mongos-host>:27017"</mongos-host>连到任意一个mongos - 进
admin库再执行:use admin→sh.stopBalancer() - 别信“连上就能用”——检查当前 shell 的
db.runCommand({isMaster:1})返回里msg字段是否含"isreplicaset: false"和"hosts"字段为空,这是mongos的典型特征
停 Balancer 前必须等 moveChunk 完成,不能只看 sh.getBalancerState()
sh.getBalancerState() 只返回布尔值,说明“是否允许运行”,不反映实际迁移状态。哪怕它返回 true,也可能正卡在一个 moveChunk 操作上——这时停 Balancer 会强制中断迁移,留下 jumbo chunk 或元数据不一致。
正确做法是双重确认:
- 执行
sh.stopBalancer()后,立即跑db.adminCommand({listCurrentOperations: 1, $all: true}) - 过滤输出找
"command": "moveChunk"或"secs_running"> 0 的长时操作 - 等所有匹配项消失,或手动用
sh.stopBalancer()+ 等待 2 分钟(它默认会等正在迁移的 chunk 完成) - 再用
sh.isBalancerRunning()验证返回false,才算真正停稳
重启 Balancer 时 timeout 参数不是万能的,超时后状态可能假成功
sh.startBalancer({timeout: 30000}) 设了 30 秒超时,不代表 Balancer 就真启动成功了。它只是“发起了启动请求”,然后等 30 秒看有没有收到确认响应。如果 config server 还没 ready、或者某个 shard 失联,sh.startBalancer() 仍可能返回成功,但 sh.isBalancerRunning() 会持续为 false。
关键判断点在日志和状态联动:
- 查
mongos日志里有没有"balancer started"和后续"starting balancing round" - 运行
sh.status(),看balancer段里currently-running是否为true,且last-chunk-migration时间在最近 5 分钟内 - 别只信返回值——
sh.startBalancer()是个 fire-and-forget 包装器,底层调的是balancerStart命令,不保证最终一致性
长期禁用 Balancer 的副作用比想象中更隐蔽
停 Balancer 几小时没问题,但超过 24 小时,分片间数据量偏差会快速放大。尤其当写入集中在某几个 chunk(比如用时间戳做片键),未迁移的 chunk 会持续膨胀,触发 jumbo chunk。这类 chunk 无法再被迁移,导致后续扩容、备份、甚至 sh.splitAt() 都失败。
生产环境建议:
- 禁用前用
sh.status()记下各 shard 的chunks数和size,作为基线 - 如果必须长期停(如跨周维护),提前手工跑
sh.moveChunk()把明显倾斜的 chunk 搬平 - 恢复 Balancer 后,盯住
config.migrations集合变化,确认迁移记录真实写入,而不是卡在pending状态
最易被忽略的一点:Balancer 关闭期间,config.settings.balancer 文档里的 stopped 字段会被设为 true,但这个字段不会自动清零——下次启动靠的是 sh.startBalancer() 调用,不是靠改配置。别以为改了配置就等于启了 Balancer。











