mongodb事务未生效的主因是未满足版本≥4.0、副本集部署、显式clientsession管理三大前提;spring的@transactional注解对mongodb默认无效,必须手动传参会话并确保所有操作共享同一session。

Spring Boot 里 MongoDB 事务没生效,大概率不是代码写错了,而是根本没满足 MongoDB 事务运行的硬性前提——版本、集群模式、会话管理这三关卡住一个,事务就直接“静默失效”,连报错都可能没有。
MongoDB 版本和部署模式不达标
4.0 以下版本压根不支持事务;4.0 只支持副本集(replica set),不支持分片集群;4.2 才开始支持分片集群事务。如果你用的是单节点 mongodb://localhost:27017 或老旧版本,@Transactional 注解或手动 withTransaction() 调用全无效。
- 检查当前 MongoDB 版本:
db.version() - 确认连接字符串是否指向副本集成员,格式必须是:
mongodb://host1:27017,host2:27017,host3:27017/?replicaSet=rs0 - 单节点部署无法开启事务,哪怕加了
startSession()也只会返回空操作
Java 客户端未正确绑定 ClientSession
MongoDB 事务不是靠注解自动织入的,它依赖显式会话(ClientSession)串联所有操作。Spring Data MongoDB 的 @Transactional 在 MongoDB 场景下**默认不生效**——它只对 JPA/MyBatis 等关系型数据源起作用。你必须手动管理会话。
- 不能每个 DAO 操作都新建一个
ClientSession,否则事务上下文断裂 - 正确做法:从
MongoClient获取一次ClientSession,传给所有参与事务的操作(如collection.insertOne(doc, options)的options.session(session)) - Spring Boot 中若想复用 Spring 事务抽象,需配合
ReactiveMongoTemplate+TransactionSynchronizationManager,但底层仍要确保会话透传
事务内执行了不支持的操作
MongoDB 对事务内允许的操作有严格限制,踩中任意一条,事务会直接失败或被静默忽略。
-
createCollection、dropCollection、renameCollection等 DDL 操作禁止在事务中调用 - 读操作必须使用与事务同一会话,且不能跨数据库(multi-document 事务仅限单库)
- 事务默认超时 60 秒,大事务需显式设置:
session.startTransaction(TransactionalOptions.builder().maxCommitTime(120, TimeUnit.SECONDS).build()) - 单次事务修改文档总大小不能超过 16MB(含 BSON 开销),超限会抛
MaxBytesPerDocumentExceededException
异常未触发 commit 或 abort
和 JDBC 不同,MongoDB 事务不会自动回滚——你必须显式调用 session.abortTransaction() 或 session.commitTransaction()。如果 catch 了异常但没 abort,或者没处理 try-finally,会话可能残留,后续操作看似成功实则未提交。
- 务必在
finally块中关闭会话:session.close() - 推荐模板写法:用
try-with-resources包裹ClientSession,并在 try 块末尾commitTransaction(),catch 块中abortTransaction() - 注意:
abortTransaction()抛异常时,会话状态已不可用,不能再调用其他方法
最容易被忽略的是:你以为加了 @Transactional 就万事大吉,但 MongoDB 根本不认这个注解;真正起作用的是那一行 session.startTransaction() 和后续所有操作是否共享该 session——漏掉任何一个环节,事务就形同虚设。











