分片事务必须走两阶段提交(2pc):先向各shard发送prepare请求,全部成功后由mongos协调config server持久化状态并统一commit/abort,链路长、延迟高、强制writeconcern: {w: "majority", j: true},且依赖config server集群时钟同步。

分片事务必须走两阶段提交(2PC)协调链路
副本集事务在单个副本集内完成,所有写操作由 primary 本地协调,WiredTiger 日志 + oplog 打包写入,路径短、无跨节点协商。而分片事务一旦涉及多个 shard,MongoDB 4.2+ 必须启用两阶段提交:先向所有参与 shard 发送 prepare 请求,等全部返回 success 后,再通知 config server 记录 config.transactions 状态,最后统一 commit 或 abort。这个过程至少增加 3~5 次跨网络往返(shard ↔ mongos ↔ config server),每跳都受网络延迟和节点负载影响。
常见错误现象:commitTransaction() 卡住 200ms 以上,mongostat 显示大量 preps 和 commits 状态延迟;Wireshark 抓包可见 mongos 与 config server 之间频繁的 coordinateCommitTransaction 请求。
- config server 不可用时,事务会阻塞在 prepare 阶段,直到超时(默认 60 秒)
- 任意一个 shard 响应慢(如磁盘 I/O 高、CPU 满载),整个事务 latency 就被拖垮
- mongos 本身不参与数据写入,但承担全部协调职责,高并发下容易成为瓶颈
writeConcern 强制 majority + journal,无法降级
无论你在 startTransaction() 时指定什么 writeConcern,分片事务的 commit 阶段**强制使用 {w: "majority", j: true}**。这意味着每个 shard 上的写入不仅要同步到多数节点,还必须刷盘落日志。副本集事务虽也推荐 majority,但你可以显式设为 {w: 1} 来换取速度——分片事务不给你这个选项。
实操建议:
- 确认所有 shard 的
wiredTiger.engineConfig.journalCompressor已设为snappy或zlib,避免 journal 写放大 - 避免在机械硬盘或低 IOPS 云盘上部署分片事务核心 shard
- 不要在事务里执行
db.collection.updateMany({x: 1}, {...}, {writeConcern: {w: 1}})—— 这个 writeConcern 会被忽略
快照隔离依赖全局逻辑时钟(Lamport Clock)同步
副本集事务用的是本地 snapshot(基于 oplog timestamp),开销小;分片事务则必须依赖 config server 维护的集群级逻辑时钟,所有 shard 在 prepare 阶段要先向 config server 拉取当前 clusterTime,再基于它构造读快照。这个同步动作在高负载下可能排队,尤其当 config server 成为热点(比如同时处理大量分片均衡或元数据变更)。
容易踩的坑:
- 事务中混用
readConcern: "local"—— 分片间看到的数据版本不一致,看似快了,但破坏 ACID - 在事务内执行聚合管道并含
$lookup跨分片集合:触发额外的协调请求,进一步拉长耗时 - 未关闭
replication.enableMajorityReadConcern:服务端启动校验失败,事务直接拒绝
驱动与服务端协议版本错配导致隐性降级
即使 MongoDB 是 4.2+,如果客户端驱动版本太老(如 Python PyMongo startTransaction() 调用会静默退化为“逐分片发写命令”,不走 2PC,也不写 config.transactions。结果是:事务看似成功,但部分分片写入后失败、无回滚,耗时反而更不可控(因为失去了协调层的统一控制)。
验证方式:
- 连接 mongos 后执行
db.runCommand({getCmdLineOpts: 1}),检查parsed.sharding是否为 true - 开启驱动 debug 日志,搜索
Starting transaction on和coordinating commit字样 - 在 config server 上查
db.getSiblingDB("config").transactions.find(),空结果大概率说明驱动未生效











