2014-04-16 89 views
4

我有2個在Sql Server數據庫中讀取和生成數據的作業。每過一段時間,作業都會與System.Transactions.TransactionInDoubtException一起崩潰。確切的堆棧跟蹤是: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' 

顯示,已經有數據庫中無死鎖,所以死鎖不能成爲理由。我在互聯網上找不到任何其他資源,它提供了有關例外原因的確切信息。那麼有沒有人知道原因可能是什麼,或者如何找到這個錯誤的根源?

回答

8

即使事務是本地的,交易仍然會升級到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 automatically escalating to MSDTC on some machines?

此外,您的內部異常是Timeout(System.Data.SqlClient.SqlException:超時過期),而不是Deadlock。雖然兩者都與阻塞有關,但它們並不是一回事。阻止時會發生一個timeout,導致應用程序停止等待被另一個連接阻止的資源,以便當前語句可以獲取該資源上的鎖。當兩個不同的連接競爭相同的資源時,會發生一個deadlock,並且它們以一種永遠無法完成的方式阻塞,除非其中一個連接終止(這就是爲什麼死鎖錯誤消息表示「事務...已經被選爲死鎖受害者「)。由於你的錯誤是一個超時,這就解釋了爲什麼你的死鎖查詢返回了一個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}」邏輯,那麼當事務處於System.Transactions.TransactionScope之內時,這可能會導致問題,因爲SQL Server自動回滾事務當發生超時或死鎖時。
+1

感謝您的回覆。事實上,錯誤已經不再發生,所以我認爲這是一個鎖定的資源造成的異常重負載導致超時,並把交易就像你已經解釋過的那樣。無論如何,你的回覆讓我更加了解原因可能是什麼。感謝那。 –

-1

我曾經有過這樣「」交易有疑問」,試圖完成交易範圍,其中包括通過實體框架映射數據庫調用。通過實體框架,其中一個呼叫是一個存儲過程,其中包括一個時select語句的命令爲「with(tablock, holdlock)」,似乎對我來說工作的解決方案是對存儲過程返回的結果調用Dispose() - 即使認爲存儲過程只是說了「Return 0」,這顯然釋放了資源