使用TransactionScope异步并行执行时MS DTC异常原因咨询
问题:TransactionScope异步并行执行触发MS DTC异常
代码场景
我们的业务代码中使用如下异步并行的事务逻辑,每个仓库操作都会创建新的DbContext及数据库连接:
using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { var task1 = _repository1.SaveAsync(dto); var task2 = _repository2.SaveAsync(dto1); await Task.WhenAll(task1 , task2).ConfigureAwait(false); transaction.Complete(); }
遇到的异常
偶尔会触发MS DTC相关错误:
System.Data.SqlClient.SqlException: Current Microsoft Distributed Transaction Coordinator (MS DTC) transaction must be committed by remote client. at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)\r\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)\r\n at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)\r\n at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
DTC配置验证
已确认MS DTC配置正常,执行PowerShell命令Test-Dtc -LocalComputerName "$env:COMPUTERNAME" -Verbose返回结果如下:
VERBOSE: ": Firewall rule for "RPC Endpoint Mapper" is enabled." VERBOSE: ": Firewall rule for "DTC incoming connections" is enabled." VERBOSE: ": Firewall rule for "DTC outgoing connections" is enabled." VERBOSE: server: AuthenticationLevel: NoAuth VERBOSE: server: InboundTransactionsEnabled: True VERBOSE: server: OutboundTransactionsEnabled: True VERBOSE: server: RemoteClientAccessEnabled: True VERBOSE: server: RemoteAdministrationAccessEnabled: True VERBOSE: server: XATransactionsEnabled: True VERBOSE: server: LUTransactionsEnabled: True
现有尝试
已找到类似讨论话题但未得到明确的原因及解决方案,目前已知将代码改为串行执行可避免错误:
using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await _repository1.SaveAsync(dto).ConfigureAwait(false); await _repository2.SaveAsync(dto1).ConfigureAwait(false); transaction.Complete(); }
核心疑问
为什么在TransactionScope中使用异步并行执行会触发MS DTC异常?
原因分析
1. 事务升级的触发逻辑
TransactionScope会创建环境事务,默认情况下,当第一个数据库连接打开时,会将该连接登记到环境事务中,此时是本地事务(无需DTC)。但在异步并行场景下:
- 两个
SaveAsync操作会同时启动,各自创建新的DbContext和数据库连接,两个连接几乎同时尝试登记到同一个环境事务中。 - 由于并行执行的时序问题,事务管理器无法将这两个连接合并到同一个本地事务中,会自动将事务升级为分布式事务(依赖MS DTC协调跨连接的事务)。
2. 异常触发的直接原因
即使DTC配置正常,异步并行的事务登记过程会打破事务上下文的同步逻辑:
- 分布式事务需要严格的时序和上下文同步,而并行执行时,两个连接的事务登记操作可能在不同的异步线程上完成,导致DTC的事务状态出现混乱。
- 这种混乱会让SQL Server误以为当前事务是由远程客户端发起的,从而抛出"必须由远程客户端提交"的异常。
3. 串行执行正常的原因
改为串行执行后,第一个连接完成事务操作并释放(或完成登记),第二个连接再打开时,事务管理器可以将其合并到已存在的本地事务中,无需升级为分布式事务,因此不会触发DTC相关异常。
内容的提问来源于stack exchange,提问作者Monadire
相关产品推荐
相关产品推荐

