sh.setBalancerWindow()需在主mongos执行并使用UTC时间格式,命令持久化至config.settings,可防意外唤醒,但不中断进行中的迁移,且必须校准配置服务器主节点的UTC时钟。

sh.setBalancerWindow() 的实际调用方式
直接在 mongos 实例中执行 sh.setBalancerWindow() 即可生效,不需要重启服务或修改配置文件。该命令会持久化写入配置服务器副本集的 config.settings 集合,下次 Balancer 启动时自动读取。
常见错误现象:命令返回成功但窗口未生效——多数是因为连接到了非主节点的 mongos,或当前配置服务器副本集主节点未同步完成。
- 必须通过主
mongos执行(sh.status()中显示mongos连接状态为connected且无警告) - 时间格式严格为 UTC,例如
"22:00"表示 UTC 时间 22:00,不是本地时区 - 起止时间不能跨日,如需覆盖凌晨,需拆成两个窗口:
["22:00", "23:59"]和["00:00", "06:00"]
为什么不能只靠 sh.stopBalancer() 做维护?
sh.stopBalancer() 是临时关停,但无法防止运维中途被意外唤醒——比如其他管理员执行了 sh.startBalancer(),或集群自动恢复(如配置服务器选举后触发 Balancer 自启)。而时间窗口是硬性策略,不受手动启停干扰。
使用场景:配合滚动升级、硬件迁移、备份窗口等需要“绝对静默期”的操作。
- 执行
sh.stopBalancer()后,仍需检查sh.getBalancerState()返回false,并确认sh.isBalancerRunning()为false - 时间窗口启用后,
sh.isBalancerRunning()在窗口外返回false,但sh.getBalancerState()仍为true(表示逻辑上开启,只是被窗口拦截) - 若窗口设置与当前时间不匹配(如设为
["02:00", "04:00"]但当前是 15:00),Balancer 会照常运行
窗口时间对迁移行为的实际影响
Balancer 不会在窗口期内发起任何新迁移,但**正在进行的迁移不会被中断**。这意味着你必须提前判断迁移是否已进入尾声,否则可能在窗口开始后仍看到 moveChunk 日志。
性能 / 兼容性影响:窗口本身无开销,但若设置过窄(如每天仅 30 分钟),会导致数据长期失衡;若跨度过长(如连续 18 小时),又失去“避开高峰”的意义。
- 建议窗口长度 ≥ 2 小时,确保有足够时间完成一个典型
moveChunk(通常 1–5 分钟,但大块可能达 20+ 分钟) - 避免将窗口设在业务低谷但网络抖动高发时段(如凌晨 3–4 点常有定时备份/监控扫描)
- 可通过
db.changelog.find({ time: { $gt: ISODate("...") } }).sort({ time: -1 }).limit(5)查看最近迁移记录,辅助判断合理窗口
容易忽略的时区陷阱
时间窗口基于配置服务器副本集主节点的系统时钟,且**强制按 UTC 解析**。如果你的配置服务器部署在 CST(UTC+8)机房,却按本地时间设 ["22:00", "06:00"],实际生效的是 UTC 22:00–06:00,即你本地时间次日 06:00–14:00——这完全反向覆盖了你的预期低峰期。
验证方法:在配置服务器主节点上运行 date -u,比对输出与你设置的窗口时间是否一致。
- 不要依赖
mongos或应用服务器的时区设置 - 若集群跨多个时区部署,统一以 UTC 规划所有窗口,避免歧义
- 修改窗口后,用
sh.getBalancerWindow()确认返回值是否为你期望的 UTC 时间段


















