首页/数据/NoSQL 速查/多文档事务使用方式
MongoDB99 条

多文档事务使用方式

复制集(4.0+)与分片集群(4.2+)支持多文档事务:通过会话 startTransaction 包住多次读写,最后统一提交或回滚。

NoSQL 速查数据更新于 2026-10-13

多文档事务是什么

多文档事务让一个会话里的多条读写要么全部生效要么全部回滚。复制集从 4.0 起支持,分片集群从 4.2 起支持。用法是取出会话(startSession),在会话上开启事务,用会话作用域的集合句柄执行读写,最后提交或回滚。事务有生命周期上限 transactionLifetimeLimitSeconds(默认 60 秒),超时会被服务端中止;事务内不适合执行建集合、建索引这类 DDL,也不应该等待外部接口。

基本信息

版本要求复制集 4.0+,分片集群 4.2+
创建会话db.getMongo().startSession()
开始与结束startTransaction / commitTransaction / abortTransaction
生命周期默认 60 秒(transactionLifetimeLimitSeconds)
读关注事务内可用 snapshot 或 majority
资源释放结束时要调用 endSession()

典型使用场景

  • 转账与对账:扣款和入账必须同时成功或同时失败
  • 订单扣库存:一次下单涉及多个集合时保证原子变更
  • 审计落地:业务写入与审计流水一起提交,避免只留下一半
  • 幂等去重:去重表记录与业务数据在同一事务里写入
  • 跨分片一致性:分片键不同的数据需要一起变更时

mongosh 示例

mongosh 示例
const session = db.getMongo().startSession()       // 取出会话
const coll = session.getDatabase("app").orders     // 会话作用域的集合句柄

session.startTransaction()                        // 开启事务
coll.insertOne({ _id: 3001, sku: "T-1", qty: 1 })  // 事务内写入
coll.updateOne({ _id: 3001 }, { $set: { status: "paid" } })

session.commitTransaction()                       // 提交
try { /* 业务逻辑 */ } catch (e) { session.abortTransaction() }  // 异常回滚
session.endSession()                              // 释放会话资源

会话操作的顺序

操作作用注意
startSession创建会话用完要 endSession,避免资源堆积
startTransaction开启事务同一会话内不能再嵌套开新事务
读写用会话句柄操作集合用外层句柄写的数据不在事务里
commitTransaction提交写冲突时可能抛出可重试错误
abortTransaction回滚异常分支必须保证被执行
事务持锁并占用缓存与 oplog,要尽量短小。不要在事务里等待外部接口或人工确认,否则很容易撞上 60 秒上限并被服务端中止。
事务里的写操作必须使用会话作用域的集合句柄;用外层 db 句柄执行的那部分写入不在事务范围内,回滚时不会被撤销,这是最容易踩的坑。

易错点

  • 事务对写冲突敏感,冲突时需应用侧重试整段事务逻辑(TransientTransactionError)
  • 把耗时几秒的外部调用放进事务,事务超时后数据库状态与业务侧认知不一致
  • 事务内执行建索引、建集合等 DDL 会报错,需要放到事务之外
  • 忘记 endSession 或异常路径没有回滚,长期运行会累积会话与锁资源

数据来源与参考

  • MongoDB Manual: Transactions
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌