必须确认的3个状态是:所有成员stateStr为PRIMARY/SECONDARY/ARBITER;无STARTUP/RECOVERING/UNKNOWN等临时状态;隐藏节点和延迟节点已手动暂停同步,且optimeDate与主节点无显著差距。

副本集滚动升级前必须确认的 3 个状态
零停机升级的前提不是“按顺序重启”,而是“每次只让一个节点不可用,且主节点切换不中断写入”。这要求你先看清当前拓扑是否真正满足条件:rs.status() 输出里每个成员的 stateStr 必须是 PRIMARY、SECONDARY 或 ARBITER;不能有 STARTUP、RECOVERING、UNKNOWN 这类临时状态。尤其注意隐藏节点(hidden: true)和延迟节点(slaveDelay)——它们不参与选举,但升级时若未手动暂停同步,可能在你升级完主节点后突然追上并触发意外 stepDown。
- 检查所有节点的
optimeDate是否与主节点相差 rs.printSecondaryReplicationInfo() 快速看) - 确认没有节点处于
ROLLBACK状态——一旦出现,说明已有数据冲突,必须人工介入,此时不能继续滚动升级 - 确保仲裁节点(
arbiterOnly: true)版本 ≥ 升级目标版本,否则新主节点可能拒绝其投票,导致选举卡住
stepDown 不等于安全交权:为什么 rs.stepDown() 后还要等 30 秒
rs.stepDown() 只是让当前主节点主动退位,并不保证新主立刻选出、也不保证写操作已全部重定向。MongoDB 默认设置下,选举需要至少 10 秒心跳超时 + 投票往返,而客户端驱动(如 Node.js 的 mongodb 包)默认重试窗口是 30 秒。直接升级刚 stepDown 的节点,极大概率遇到 NotPrimaryNoSecondaryOk 错误或写入丢失。
- 执行
rs.stepDown(30)(参数单位秒),强制它至少 30 秒内不参选,给集群留出稳定窗口 - 紧接着运行
rs.status(),确认stateStr已变为SECONDARY,且新主节点的electionId已更新 - 在应用层发一条带
w: "majority"的测试写入,验证写操作能成功返回——别只看mongosh里的提示
升级命令与二进制替换的顺序陷阱
很多人以为“停 mongod → 换二进制 → 启动”就完了,但副本集节点启动时会校验 oplog 兼容性。4.4 升 5.0 可以直接换,但 5.0 升 6.0 必须先在旧版本中运行 db.adminCommand({setFeatureCompatibilityVersion: "5.0"}),否则新进程启动失败并报错 Invalid feature compatibility version。这个命令必须在旧主节点上执行,且所有节点都完成升级前不能设为 "6.0"。
- 升级前统一执行
db.adminCommand({getCmdLineOpts: 1}),确认各节点的storage.engine一致(WiredTiger 是唯一支持选项) - 替换二进制后,用
mongod --version验证,再用mongod --config /etc/mongod.conf --dryRun检查配置兼容性 - 启动时加
--bind_ip_all(或明确列出 IP)而非--bind_ip localhost,否则升级后节点无法被其他成员发现
升级后最易忽略的兼容性检查点
版本号变了不代表一切就绪。6.0 默认启用 featureCompatibilityVersion: "6.0",但这是个单向开关——一旦设了就不能降回 5.0。更隐蔽的问题是索引行为变化:例如 6.0 中 text 索引对空字符串的处理更严格,如果应用依赖旧逻辑,查询可能突然不命中;还有聚合管道中 $merge 默认写入模式从 replace 改为 merge,不显式指定 on 字段会报错。
- 升级完所有节点后,立刻运行
db.adminCommand({getFeatureCompatibilityVersion: 1}),确认仍是旧版本(如"5.0") - 用
db.runCommand({listCommands: 1})查看新命令是否存在,比如 6.0 新增的refreshLogicalSessionCacheNow,可用来验证进程确实跑在新二进制上 - 重点检查应用日志里是否有
deprecationWarning字样——MongoDB 不会中断服务,但会悄悄记录即将废弃的行为,这些就是下次升级的雷
真正的难点不在步骤多,而在每个节点的状态、每个命令的隐含约束、每个驱动的重试策略之间存在微小的时间差和语义差。盯住 rs.status() 和应用写入成功率,比背流程重要得多。

















