MongoDB事务未正确回滚:重复插入后首次操作未回滚
问题分析与解决方案
你的核心错误是事务中的数据库操作没有关联到开启的session,导致两次插入操作都不在事务上下文范围内,第一次插入直接提交到数据库,自然不会被回滚。
具体原因
MongoDB的事务是基于IClientSessionHandle会话对象的,所有需要纳入事务管理的操作,必须在调用时传入这个session对象。你当前的InsertItem方法调用InsertOneAsync时没有传递session,所以两次插入都是独立的非事务操作,和你开启的事务完全无关。
修正步骤
- 修改
InsertItem方法,添加IClientSessionHandle参数,并在插入时传入该session - 在
TestyInsertItem中调用InsertItem时传递开启的session - 补充事务正常完成时的
CommitTransactionAsync调用(原代码缺少提交逻辑,即使没有异常也不会提交事务)
修正后的代码示例
public async Task<Item> InsertItem(IClientSessionHandle session, Item item, string appId) { var itemAppCollection = _divitiaeDatabase.GetCollection<Item>(appId); // 插入操作传入session,纳入事务管理 await itemAppCollection.InsertOneAsync(session, item); return item; } public async Task TestyInsertItem(Item item, string appId) { var sessionOptions = new ClientSessionOptions { CausalConsistency = true }; using (var session = await _divitiaeClient.StartSessionAsync(sessionOptions)) { session.StartTransaction(); try { // 调用InsertItem时传递session await InsertItem(session, item, appId); await InsertItem(session, item, appId); // 无异常时提交事务 await session.CommitTransactionAsync(); } catch (Exception ex) { await session.AbortTransactionAsync(); throw; } } }
额外注意事项
- 确保你的MongoDB环境支持事务:MongoDB 4.0及以上版本,且部署为副本集或分片集群,单节点MongoDB默认不支持事务(测试环境可通过配置启用,但生产环境必须使用副本集/分片)。
内容的提问来源于stack exchange,提问作者Nono-Man
相关产品推荐
相关产品推荐

