mongodb升级中fcv与二进制版本必须分离操作,因fcv控制内部功能开关(如索引、oplog、事务语义),而二进制决定协议和命令支持;二者不匹配会导致启动失败或功能异常,故须严格按“先设fcv=旧版→再换二进制→最后升fcv”三步执行。

MongoDB 4.0 分片集群不能直接升级到 4.2,必须先将 featureCompatibilityVersion(FCV)升到 4.0,再升级二进制,最后将 FCV 升到 4.2 —— 顺序错一步,mongod 就会拒绝启动。
为什么 upgrade 版本和 FCV 要分开操作
FCV 控制的是 MongoDB 内部功能开关,比如索引构建行为、oplog 格式、事务语义等;而二进制版本决定你能运行哪些命令、支持哪些 wire protocol。4.2 的二进制在 FCV=4.0 模式下能跑,但会禁用 4.2 新特性(如通配符索引默认启用、更严格的聚合 pipeline 验证),且不允许你直接把 FCV 设成 4.2。反过来,如果 FCV 已设为 4.2 但二进制还是 4.0,mongod 启动时会报错:featureCompatibilityVersion must be 4.0 when running with binary version 4.0。
所以必须严格按三步走:
- 确认所有节点 FCV=4.0(通过
db.adminCommand({getParameter: 1, featureCompatibilityVersion: 1})检查) - 逐个替换 mongod/mongos 二进制为 4.2 版本(先 config server,再 shard,最后 mongos)
- 全部二进制就位后,统一执行
db.adminCommand({setFeatureCompatibilityVersion: "4.2"})
分片集群升级顺序不能乱:config server → shard → mongos
config server 是整个集群的“大脑”,存储分片元数据、chunk 分布、balancer 状态。如果先升 mongos,它可能因协议不兼容无法连接 config server,导致路由失效;如果先升某个 shard,而 config server 还是 4.0,它可能拒绝接收来自 4.2 shard 的心跳或 chunk 迁移请求。
实操建议:
- 先停掉 balancer:
sh.stopBalancer()(在任意 mongos 上执行) - 升级所有 config server 节点(必须是副本集,逐个 secondary → primary)
- 升级每个 shard 副本集:按常规副本集方式,先 secondary 再 primary
- 最后升级所有 mongos 实例(无状态,可一次性换完)
- 全部完成并验证
mongod进程正常后,再升 FCV
升级后必须验证的三项关键行为
4.2 对分片逻辑有实质性调整,尤其影响稳定性:
-
moveChunk命令不再允许指定_secondaryThrottle: true,该参数已被移除。如果你的应用或运维脚本里还硬编码了这个字段,会报错unrecognized field '_secondaryThrottle' - balancer 默认启用
enableSharding的自动 chunk 拆分,但 4.2 开始要求集合必须有合法的 shard key 才能拆分,否则 chunk 会长期卡住不动 —— 查看sh.status()中是否有pending状态的 chunk - 4.2 的
explain("executionStats")在跨分片查询中会显示remoteExplain字段,但旧驱动(如 Java Driver 3.11 以下)可能解析失败,引发ClassCastException或空指针
最容易被忽略的降级风险
一旦执行了 setFeatureCompatibilityVersion: "4.2",就不能再降级回 4.0 二进制 —— 不是“不推荐”,是根本启动不了。MongoDB 会检查数据文件中的内部标记,发现 FCV=4.2 就直接 abort。所以:
- FCV 升级前,必须确保所有 mongos 和应用驱动都已更新到 4.2 兼容版本(例如 Node.js Driver ≥ 3.6.0,Python PyMongo ≥ 3.11.0)
- 备份必须包含 FCV=4.0 状态下的完整快照,而不是只备份数据目录(因为 FCV 是写在 local 数据库里的)
- 不要在凌晨或大促前执行 FCV 切换;它本身不耗时,但触发的后台清理(如旧 oplog 条目回收)可能短暂影响主节点 CPU 和 I/O











