sh.isBalancerRunning() 返回true或false,仅表示Balancer进程是否启用并运行中,不反映是否有chunk正在迁移;true不代表有迁移进行,false也不代表迁移已停止。
sh.isBalancerRunning() 返回什么,代表什么状态?
是一个 shell 函数,它只返回
或
,**不代表迁移是否在进行中,只表示 Balancer 进程本身是否处于“启用并运行中”的状态**。很多人误以为它能告诉你“当前有没有 chunk 正在迁移”,其实不能——Balancer 可能开着,但没活干;也可能刚被手动停掉,而迁移还在收尾。
常见错误现象:
返回
,但
显示没有 pending migration;或者返回
,却发现某个 shard 上的
命令仍在执行(这是合法的,迁移一旦开始就不会被 Balancer 状态中断)。
它不反映迁移队列长度、chunk 移动速度、卡住的迁移任务
它不受单次
手动操作影响——那些是绕过 Balancer 的直接命令
如果 Balancer 被禁用(
),它返回
;启用后需等待下一轮调度周期(默认 5 秒)才可能真正运行
真正能查迁移进度的命令有哪些?
要看实时迁移动作,得盯住后台正在执行的
操作,以及分片元数据变更。核心手段有三个:
查正在运行的迁移任务:
,重点过滤
和
操作
查迁移历史和卡点:
,注意
/
字段和
,失败记录里常带
看实时 chunk 分布变化:
中的
行,对比前后两次输出的各 shard chunk 数,差值 > 0 表示迁移已生效;若某 shard 的
长时间不更新,说明迁移卡在 commit 阶段
为什么 sh.status() 里的 “balancer is running” 不等于迁移正在进行?
输出顶部那句
,本质就是调用了
,它只是读取
集合中
文档的
字段(
表示启用)。这个字段控制 Balancer 是否会在下次调度时拉取待迁移 chunk,但完全不感知当前是否有活跃迁移。
MongoDB For Windows v3.5.4
MongoDB For Windows v3.5.4
下载
典型误导场景:
Balancer 启用中,但所有 shard 的 chunk 分布已均衡(
你刚执行
,这个迁移不会出现在 Balancer 日志里,也不会触发
的任何变化
迁移因网络超时失败,Balancer 会重试(默认 5 次),但
仍为
,你得去
查失败原因
生产环境建议监控哪几个关键指标?
靠单一函数判断迁移进度风险很高。实际运维应组合采集以下信号:
:过去 5 分钟发起的迁移数,突增可能意味着自动均衡启动或手动干预
:运行超 30 秒的迁移,大概率异常(如锁冲突、磁盘慢、目标 shard 内存不足)
中各 shard 的
连通性 +
是否指向预期 shard
操作系统层监控:源/目标 shard 的磁盘 IO wait、网络丢包率、mongod 进程 RSS 内存——迁移期间
会大量读写数据文件,这些指标比 Balancer 状态更能提前预警
最容易被忽略的是:迁移完成不等于数据立即可读。新 chunk 在目标 shard 上写入后,config server 更新路由表有短暂延迟(通常 StaleConfig 错误——这不属于 Balancer 监控范畴,得靠驱动日志或
的
调用来确认。
sh.isBalancerRunning()truefalsesh.isBalancerRunning()truesh.status()falsemoveChunkmoveChunksh.stopBalancer()falsemoveChunkdb.adminCommand({ "currentOp": { "secs_running": { "$gt": 0 }, "secs_running": { "$lt": 3600 }, "active": true, "ns": "config.*", "secs_running": { "$gt": 10 } } })moveChunkcommitChunkMigrationdb.changelog.find({ "what": "moveChunk" }).sort({ "_id": -1 }).limit(5)fromtotimeerrmsgsh.status({ verbose: true })chunkssizesh.status()balancer is runningsh.isBalancerRunning()config.settings_id: "balancer"stoppedfalsediffsh.moveChunk("db.coll", { _id: 1 }, "shard01")sh.isBalancerRunning()sh.isBalancerRunning()truechangelogdb.changelog.countDocuments({ "what": "moveChunk", "time": { "$gt": ISODate(Date.now() - 5 * 60 * 1000) } })db.currentOp().inprog.filter(op => op.secs_running > 30 && op.what === "moveChunk")db.getSiblingDB("config").shards.find().toArray()hostdb.getSiblingDB("config").databases.findOne({ _id: "db" }).primarymoveChunkmongosgetShardVersion