MongoDB 在执行版本降级之前,有一个关键前置步骤绝不能省略:必须先将 featureCompatibilityVersion(fCV)降到目标版本。例如,从 5.0 回退到 4.4 时,需要在 Primary 节点执行 db.adminCommand({setFeatureCompatibilityVersion:"4.4",confirm:true})。同时还必须满足几个前提条件:所有节点都必须在线,集群中不能存在初始同步任务,也不能处于重分片流程中。如果跳过这一步,直接替换二进制文件后再启动,通常都会导致 MongoDB 启动失败。

降级前必须先降 featureCompatibilityVersion
如果只是单纯替换二进制文件,MongoDB 版本降级是无法成功的。官方要求非常明确:必须先把 featureCompatibilityVersion(fCV)调整为目标版本,然后才能继续后续降级操作。比如从 5.0 降级到 4.4,必须先在 admin 数据库中执行:
db.adminCommand({ setFeatureCompatibilityVersion: "4.4", confirm: true })需要注意,这条命令不能在任意节点执行,只能在 Primary 节点上运行;此外,副本集中的所有节点都必须保持在线,不能存在正在进行初始同步的节点,也不能有正在执行的重新分片任务。否则,即使你已经替换成 4.4 版本的 mongod 二进制,服务依然无法正常启动。只要 fCV 仍然保持为 "5.0",MongoDB 启动时就会直接报错退出,并提示 FeatureCompatibilityVersion mismatch。
5.0 → 4.4 降级要清理不兼容数据
MongoDB 从 5.0 降级到 4.4,并不是换完二进制就结束了。因为 5.0 引入的一些数据格式和配置,在 4.4 中并不兼容:
- 字段名中包含
.或$的文档,必须提前删除或重命名,否则 4.4 启动时会拒绝加载对应集合 - 如果集群使用过
setDefaultRWConcern设置集群级读写关注,需要手动恢复为 4.4 的默认配置,否则某些命令可能出现Unknown field报错 - 如果部署环境启用了 Slim 格式时区文件(
--timeZoneInfo),则必须降级到 4.4.7 及以上小版本,或者改回传统格式的时区文件 - 对于包含仲裁节点(arbiter)的副本集,还要确认
replication.enableMajorityReadConcern配置与 4.4 兼容,必要时增加--enableMajorityReadConcern false
滚动降级时 Primary 节点怎么处理
在 MongoDB 副本集滚动降级过程中,不能直接停止 Primary 后替换二进制文件。这样做会触发非受控选举,可能带来写入丢失或数据回滚风险。更稳妥的标准做法如下:
- 先确认至少有一个 Secondary 节点处于
SECONDARY状态,并且同步延迟小于 10 秒(可通过rs.status().members[n].optimeDate检查) - 在当前 Primary 节点执行
rs.stepDown(30),让其主动让出主节点角色,并在 30 秒内不参与竞选 - 等待新的 Primary 选举完成且状态稳定后,再停止刚刚降级下来的原 Primary,替换为 4.4 版本的
mongod并启动 - 该节点重启后会以 Secondary 身份重新加入副本集,待数据同步完成后,再根据需要决定是否恢复其参选资格(通常需要调整
priority)
降级后最容易被忽略的验证点
很多人在完成 MongoDB 降级后,会以为替换完二进制、修改完 fCV 就算结束,但实际问题往往出现在这些容易忽略的兼容性检查上:
- 检查
rs.status().members[n].version,确认所有节点都已经运行在 4.4.x,避免副本集内出现版本混用 - 执行
db.runCommand({ listCommands: 1 }),确认没有 5.0 特有命令残留,例如reshardCollection - 应用连接数据库后,执行一次带
w: "majority"的写操作,验证写关注是否正常生效——因为 4.4 默认并不启用 majority read concern,这可能影响实际行为 - 特别要注意:降级完成后,通常无法直接再升级回 5.0,除非重新执行备份恢复;一旦 fCV 已降下去,就不具备可逆性,除非相关数据已被清空
