mongodb 4.2分片集群启用跨分片事务需同时满足四类硬性条件:拓扑上所有shard及config server必须为三节点副本集、mongos≥4.2;驱动与uri版本匹配;代码中显式设置readconcern:"snapshot";且集合须预先分片、非capped/system类。

MongoDB 4.2 分片集群能启用跨分片事务,但不是“连上 mongos 就自动可用”——必须同时满足拓扑、配置、驱动和代码层共四类硬性条件,缺一不可。
确认分片集群是否满足事务拓扑前提
事务在分片集群上是“有门槛的”,伪分片或单节点 shard 会直接拒绝事务请求,常见报错如 Transaction numbers are only allowed on a replica set member or mongos config server 或 NotMaster。
- 每个 shard 必须是三节点副本集(
rs.status()中能看到至少 3 个成员),单节点 shard 不行 - config server 必须是副本集(
csReplSet),不能是旧版 standalone configdb -
mongos进程需连接到该 config server 副本集,且自身版本 ≥ 4.2 - 运行
sh.status(),输出中每个 shard 的state应为1,shardingVersion≥1 - Docker Compose 拉起的 “1 mongos + 1 shard(单 mongod)” 属于典型伪分片,不满足条件
连接 URI 和驱动版本必须匹配
客户端驱动不升级,即使服务端达标也用不了事务;URI 缺关键参数,Spring Boot 也不会自动配 MongoTransactionManager。
- 连接 URI 必须指向
mongos地址(如mongodb://mongos0:27017,mongos1:27017/?maxPoolSize=100),不能直连 shard 节点 - PyMongo 版本 ≥ 4.2,Node.js Driver ≥ 4.13,Spring Data MongoDB ≥ 3.3(对应 Spring Boot 2.7+)
- Spring Boot 中若使用
@Transactional,需确保spring.data.mongodb.uri包含多个 mongos 地址或明确指定replicaSet参数(虽非必需,但可辅助识别拓扑) - Java 客户端显式创建
MongoClient时,需传入ClusterSettings并启用readConcernLevel支持
事务必须显式声明 readConcern: "snapshot"
分片环境下默认读关注不生效,漏设会导致操作直接失败,哪怕只写不读也可能因驱动隐式元数据读取而中断。
- 必须在
session.startTransaction()时传入选项,不能在insertOne()等单个操作里加:session.startTransaction({ readConcern: { level: "snapshot" } }) - Node.js 示例中若写成
collection.insertOne(doc, { session })但没设 transaction-levelreadConcern,仍会报错Read concern 'snapshot' is not available for this operation - Spring Boot 的
@Transactional注解不自动注入readConcern,必须配合自定义TransactionDefinition或手动管理ClientSession - 事务内所有集合必须已预先分片(
sh.shardCollection()执行过),且不能是capped、system.*或config/admin/local数据库中的集合
注意运行时限制和模式设计权衡
事务不是银弹,开启后要盯住几个容易被忽略的边界点。
- 默认事务生命周期上限为 60 秒(
transactionLifetimeLimitSeconds),超时即中止;分片集群需在所有 shard 副本集成员上统一调整该参数 - 事务内无法跨分片隐式创建新集合——比如一个操作写 shard A 的
orders,另一个操作试图写 shard B 的未建集合logs,会直接失败 - WiredTiger 缓存压力大时(如大事务未提交),可能触发
TransactionTooLargeForCache错误且不再重试(MongoDB ≥ 6.2) - 多数业务场景下,嵌入式文档 + 单文档原子性仍是更轻量、更可靠的选择;事务应留给真正需要跨集合强一致性的环节,比如金融账务核对











