一尘不染

System.Transactions.TransactionInDoubtException的原因

sql

我有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)

我在Google上搜索了一下,找到了有关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'

显示数据库上没有死锁,因此死锁不可能是原因。我在互联网上找不到任何其他资源可以提供有关异常原因的确切信息。那么,有人知道原因可能是什么,或者如何找到此错误的根源?


阅读 219

收藏
2021-03-10

共1个答案

一尘不染

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

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

* 事务中至少有两个支持单阶段通知的持久资源。例如,加入的单个连接不会导致事务升级。但是,每当您打开与数据库的第二个连接而导致该数据库加入时,System.Transactions基础结构都会检测到它是事务中的第二个持久资源,并将其升级为MSDTC事务。

注意:我已经阅读了一些文章,指出这仅适用于SQL 2005,并且SQL 2008+对于MSDTC升级更为精明。这些说明SQL 2008仅 在同时
打开多个连接时才会升级为MSDTC

另外,您的内部异常是Timeout(System.Data.SqlClient.SqlException:超时已过期),而不是Deadlock。虽然两者都与阻止有关,但它们不是同一件事。timeout当阻止导致应用程序停止等待被另一个连接阻止的资源时发生A
,以便当前语句可以获取对该资源的锁定。一deadlock,当两个不同的连接都用相同的资源竞争他们的方式阻止他们将永远无法完成,除非其中一个连接被终止时,以及(这是为什么僵局错误信息说:“交易......已经选择作为僵局的受害者”)。由于您的错误是超时,因此这说明了死锁查询返回0计数的原因。

System.Transactions.TransactionInDoubtException来自MSDN(http://msdn.microsoft.com/zh-
cn/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}”逻辑,则当事务在内时,这可能会引起问题System.Transactions.TransactionScope,因为SQL Server在超时或超时时会自动回滚事务的方式发生死锁。
2021-03-10