MongoDB事务要求所有副本集或分片集群成员使用同一主版本号(如全部为7.0.x),否则因oplog格式、锁语义、2PC元数据等底层协议不兼容而静默失败或报错。

MongoDB 事务要求所有副本集或分片集群成员使用同一主版本号(如全部为 7.0.x),否则事务会静默失败或直接报错——这不是配置问题,而是协议层不兼容导致的硬性限制。
为什么事务在混合版本中会失败
事务依赖 oplog 格式、锁管理语义、两阶段提交(2PC)元数据结构等底层机制。这些在不同主版本间存在不可忽略的变更:
-
6.0引入了新的事务状态字段和prepare阶段日志条目格式,5.0节点无法解析,直接跳过或丢弃 -
7.0的事务心跳包携带txnNumberV2字段,6.0mongos 会因未知字段拒绝转发,导致writeConcern: {w: "majority"}永久超时 - 即使所有节点都“连得上”,
rs.status()显示SECONDARY,事务仍可能卡在inProgress状态,日志里只有一行Skipping op with unknown operation type
setFeatureCompatibilityVersion 不是事务开关,而是数据格式锁
setFeatureCompatibilityVersion 控制的是“能否写入新格式数据”,不是“是否启用事务”。它生效的前提是:所有节点二进制版本已就位,且数据文件已完成格式迁移。
- 执行
db.adminCommand({setFeatureCompatibilityVersion: "7.0", confirm: true})前,必须确保每个mongod进程都是7.0+二进制,否则报错expected fcv 7.0, got 6.0 - fCV 升级后不会立刻重写磁盘数据,但后续新写入的文档、索引、oplog 条目都会按
7.0格式编码;旧格式数据仍可读,但无法被6.0节点安全同步 - 事务失败常发生在 fCV 已设为
7.0,但某个mongos或 config server 还是6.0——此时路由表更新失败,sh.status()看不到 chunk 分配,事务找不到可用 shard
升级过程中最容易被忽略的三个检查点
很多团队卡在“看起来都升级完了,但事务还是报错”,问题往往出在这些非显性环节:
- 没验证
mongos --version:分片集群中mongos是独立进程,容易漏升;mongos 6.0连接mongod 7.0shard 时,事务请求会被截断,无明确错误返回 - systemd service 文件残留:
/etc/systemd/system/mongod.service中的ExecStart=可能仍指向旧版/usr/bin/mongod,systemctl restart mongod实际启动的是6.0二进制 - fCV 设置顺序错误:在分片集群中,必须先升级并设置所有 config server 的 fCV,再升级 shard,最后升级
mongos;如果先设了shard的 fCV 为7.0,但 config server 还是6.0,balancer 会拒绝写入新 chunk 元数据,事务路由失效
真正决定事务是否可用的,从来不是单个命令是否成功,而是所有组件二进制版本、fCV 值、网络协议能力三者是否严格对齐——差一个点,事务就停在半路,而日志里往往只留一行模糊提示。


















