sh.status()中balancer部分仅显示是否启用、是否运行中、最近成功迁移时间;不反映待迁移chunk、队列状态、延迟或分布偏差,诊断需查config.migrationHistory、mongos日志及config.chunks聚合统计。
直接看 sh.status() 输出里 balancer 段,核心就三件事:是否启用、是否正在运行、最近一次成功迁移时间。它不告诉你“接下来要搬哪块 chunk”,也不显示排队中的迁移任务——这些得查 config 数据库或日志。
常见误解是把 "enabled": true 当成“此刻正在搬数据”,其实只是开关打开;而 "currentlyRunning": true 才代表有迁移任务在执行中(哪怕只有一条)。
"enabled": false 表示平衡器被手动停用(sh.stopBalancer()),即使集群严重倾斜也不会自动处理"currentlyRunning": true 但 "activeWindow": null,说明没设活动窗口,平衡器全天候工作"lastSeen": "..." 时间戳超过 1 小时,大概率迁移卡住了,得查 config.migrationHistory 或 mongos 日志里的 moveChunk 错误activeWindow 是平衡器“允许干活”的时间范围,并非 cron 式调度。它只控制迁移启动时机,不中断已在进行的迁移。一旦迁移开始,就算超出窗口也会跑完。
设置方式是调用 sh.setBalancerWindow(),传入 UTC 时间段(注意不是本地时区):
sh.setBalancerWindow( { start: "22:00", stop: "06:00" } )
这个配置写在 config.settings 集合里,所有 mongos 共享。如果多个 mongos 同时执行该命令,后写的会覆盖前写的——没有合并逻辑。
"HH:MM",不支持秒、时区缩写或 AM/PM"22:00" 到 "06:00")是合法的,内部按 UTC 处理null:sh.setBalancerWindow(null),别用空对象sh.status() 的 balancer 块是状态快照,不是监控仪表盘。它不包含实时负载、延迟、chunk 数量差值等指标——那些得自己算。
比如判断是否失衡,不能只看 "currentlyRunning": false,还要查各 shard 的 chunk 总数:
db.getSiblingDB("config").chunks.aggregate([ { $group: { _id: "$shard", count: { $sum: 1 } } } ])
再结合 db.getSiblingDB("config").tags.find() 看分片标签规则,才能确认是不是策略导致的“假失衡”。
chunkSize、网络延迟、目标 shard 磁盘压力影响,sh.status() 不反映这些moveChunk 失败(如目标 shard 写满),错误只记在 mongos 日志和 config.migrationHistory,sh.status() 里只会显示 "lastSeen" 停滞sh.status() 输出的 "migrationCount" 是历史累计值,不是当前队列长度,无法用于判断积压sh.stopBalancer() 是安全停用:它先等待当前迁移完成,再更新 config.settings 并广播给所有 mongos。而手动 update config.settings 里的 balancer 文档,会立刻生效但可能中断迁移,导致数据不一致或锁残留。
恢复时也一样:sh.startBalancer() 会校验集群健康状态(如所有 shard 可达),而直接改回 "enabled": true 不做任何检查。
sh.stopBalancer(),别绕过 shell 封装sh.stopBalancer() 卡住超过 30 秒,大概率有迁移阻塞,需查 config.locks 里 "_id": "balancer" 的 state 字段是否为 2(表示被其他操作锁住)sh.status() 隐藏了太多上下文依赖:时间窗口的 UTC 语义、迁移中断的边界条件、停用操作的原子性保障。真要靠它诊断问题,得随时准备好翻 config.migrationHistory 和 mongos 日志。