System.Transactions.TransactionInDoubtException的原因

Tim*_*ter 6 .net sql sql-server transactions

我有2个作业在Sql Server数据库中读取和生成数据.每隔一段时间,作业就会因System.Transactions.TransactionInDoubtException而崩溃.确切的堆栈跟踪是:

 Unhandled Exception: System.Transactions.TransactionInDoubtException: The transaction is in doubt. ---> System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception: The wait operation timed out. Exitcode: -532462766
    --- End of inner exception stack trace ---
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
    at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
    at System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
    at System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
    at System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
    at System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value)
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
Run Code Online (Sandbox Code Playgroud)

我搜索了一下有关MSDTC的一些信息,但我认为这不是问题,因为事务应该是本地的,因为作业只能在单个数据库上运行.以下查询:

SELECT cntr_value AS NumOfDeadLocks
  FROM sys.dm_os_performance_counters
 WHERE object_name = 'SQLServer:Locks'
   AND counter_name = 'Number of Deadlocks/sec'
   AND instance_name = '_Total'
Run Code Online (Sandbox Code Playgroud)

表明数据库上没有死锁,所以死锁不是原因.我在互联网上找不到任何其他资源,它提供了有关异常原因的确切信息.所以有人知道原因是什么或如何找到这个错误的根源?

Bat*_*ech 11

即使事务是本地事务,如果您在同一事务范围内打开多个连接,事务仍将升级到MSDTC,根据这篇文章:http://msdn.microsoft.com/en-us/library/ms229978(v = vs.110)的.aspx

导致System.Transactions基础结构将事务所有权转移到MSDTC的升级发生在:...

  • 在事务中登记至少两个支持单阶段通知的持久资源.例如,登记单个连接不会导致事务被提升.但是,每当打开导致数据库登记的数据库的第二个连接时,System.Transactions基础结构都会检测到它是事务中的第二个持久资源,并将其升级为MSDTC事务.

注意:我已经阅读了一些文章,声明这仅适用于SQL 2005,并且SQL 2008+对于MSDTC促销更为明智.该SQL 2008当多个连接是开放的,只会促进MSDTC这些国家在同一时间.请参阅:TransactionScope在某些计算机上自动升级到MSDTC?

此外,您的内部异常是Timeout(System.Data.SqlClient.SqlException:Timeout expired),而不是a Deadlock.虽然两者都与阻止有关,但它们并不是一回事.timeout当阻塞导致应用程序停止等待被另一个连接阻塞的资源时,会发生A ,以便当前语句可以获取该资源上的锁.deadlock当两个不同的连接竞争相同的资源时会发生A ,并且它们以一种永远无法完成的方式阻塞,除非其中一个连接被终止(这就是为什么死锁错误消息说"事务...已被选中"作为僵局受害者").由于您的错误是超时,这解释了为什么您的死锁查询返回0计数.

System.Transactions.TransactionInDoubtException来自MSDN(http://msdn.microsoft.com/en-us/library/system.transactions.transactionindoubtexception ( v=vs.110 ) .aspx)声明:

在对有疑问的事务尝试操作时抛出此异常.当无法确定交易状态时,交易存在疑问.具体而言,交易的最终结果,无论是提交还是中止,从未为此交易所知.

当尝试提交事务并且事务变为InDoubt时,也会抛出此异常.

原因是:在此期间发生的TransactionScope事情导致其在交易结束时的状态未知.

原因:可能有许多不同的原因,但如果没有发布源代码,很难确定您的具体原因.

要检查的事项:

  1. 如果您使用的是SQL 2005,并且打开了多个连接,则您的事务将被提升为MSDTC事务.
  2. 如果您使用的是SQL 2008+,并且您同时打开了多个连接(即嵌套连接或并行运行的多个ASYNC连接),则事务将被提升为MSDTC事务.
  3. 如果您的代码中运行了"try/catch {retry if timeout/deadlock}"逻辑,那么当事务处于a内时,这可能会导致问题System.Transactions.TransactionScope,因为SQL Server在超时时自动回滚事务或发生死锁.


小智 6

我认为没有 MSDTC 也可能发生这种情况。我想我在一个根本不使用 MSDTC 的系统中也发生过这种情况。我认为如果您的数据库连接在某个时刻失败,就会触发它。此时必须是服务已向数据库发送 COMMIT,但随后连接失败,因此服务无法确定数据库是否收到了 COMMIT 命令。