maintenancemode不是维护模式开关,仅标记secondary节点退选以避免被选为primary,完全不阻止写入;必须通过rs.reconfig()设priority=0并添加maintenancemode=true生效,且恢复时须同步复位priority。

什么是 maintenanceMode,它真能停掉主节点写入?
maintenanceMode 是 MongoDB 副本集成员的一个内部状态标记,**不是真正的“维护模式开关”**。它只影响该成员是否参与选举和是否能被选为 PRIMARY,**完全不阻止写入**——如果当前 PRIMARY 还在运行,应用照常写入,该成员即使设了 maintenanceMode: true 仍会持续同步 oplog。
它的实际作用是:让这个节点“主动退选”,避免在维护期间(比如升级、磁盘扩容)意外被选为主节点,从而导致写入中断或数据不一致。
- 仅对
SECONDARY成员生效;对PRIMARY手动设置会被忽略(MongoDB 会静默丢弃) - 设置后该节点状态变为
SECONDARY(如果原本就是),但stateStr末尾会追加(maintenanceMode) - 必须通过
rs.reconfig()修改成员配置,不能用rs.stepDown()或db.adminCommand({replSetMaintenance: 1})—— 后者是旧版已废弃的伪命令,无实际效果
怎么给 secondary 节点开启 maintenanceMode?
核心操作是调用 rs.reconfig(),动态更新该成员的 priority 和新增 maintenanceMode 字段。注意:必须在 PRIMARY 上执行,且配置版本号要递增。
示例(假设目标节点 host 是 "rs2.example.com:27017"):
cfg = rs.conf();
idx = cfg.members.findIndex(m => m.host === "rs2.example.com:27017");
cfg.members[idx].priority = 0;
cfg.members[idx].maintenanceMode = true;
cfg.version++; // 必须自增
rs.reconfig(cfg, {force: true});
-
priority: 0是关键前提——maintenanceMode只有在priority === 0时才被识别并生效 -
{force: true}在多数场景下需要,尤其当 PRIMARY 刚重启或网络抖动后,避免 “conflicting operation” 错误 - 执行后立即检查:
rs.status().members.find(m => m.name === "rs2.example.com:27017"),确认stateStr包含(maintenanceMode)
为什么 setMaintenanceMode 命令不存在?
很多人搜到 db.adminCommand({setMaintenanceMode: 1}) 或类似写法,这是典型误区。MongoDB **从未提供过这个命令**,官方文档也无此条目。所有尝试都会返回:
{ "ok" : 0, "errmsg" : "no such cmd: setMaintenanceMode", "code" : 59, "codeName" : "CommandNotFound" }
混淆来源可能是早期 JIRA 讨论、第三方工具封装,或把 replSetMaintenance(v3.2–3.6 中短暂存在、仅用于内部测试的调试命令)误传为正式功能。v4.0+ 已彻底移除该命令,唯一正解只有 rs.reconfig() 动态改配置。
- 别依赖 shell 自动补全——
rs.按 tab 不会列出任何 *maintenance* 相关方法 - 监控脚本里硬编码该命令会导致静默失败,务必用
rs.status()的返回值校验状态,而非命令是否“成功返回”
退出 maintenanceMode 时最容易漏掉什么?
恢复的关键不是删掉 maintenanceMode 字段,而是**必须同时恢复 priority 值**,否则节点永远无法参选。
错误做法(只删字段):
cfg.members[idx].maintenanceMode = undefined; // ❌ 不够!
正确做法(两步缺一不可):
cfg.members[idx].maintenanceMode = undefined;
cfg.members[idx].priority = 1; // ✅ 必须显式设回原值(如原来是 1)
cfg.version++;
rs.reconfig(cfg, {force: true});
- 如果忘了恢复
priority,该节点将长期卡在SECONDARY (maintenanceMode),即使副本集其他节点全部宕机也无法接管 - 建议维护前先用
rs.conf()记录原始priority和votes,避免恢复时凭记忆填写出错 -
maintenanceMode不影响hidden、delayed等其他属性,但若节点同时设了hidden: true,需额外确认读请求是否绕过了它
真正麻烦的从来不是设上,而是设完之后没人记得 priority 要复位。











