[英]TransactionInDoubtException using System.Transactions on SQL Server 2005
這篇文章的基本問題是“為什么非升級的LTM交易會受到質疑?”
我收到System.Transactions.TransactionInDoubtException,我無法解釋原因。 不幸的是我無法重現這個問題,但根據跟蹤文件它確實發生了。 我正在使用SQL 2005,連接到一個數據庫並使用一個SQLConnection,所以我不希望進行促銷。 錯誤消息表示超時。 但是,有時我得到一條超時消息,但異常是事務已中止而不是有疑問,這更容易處理。
這是完整的堆棧跟蹤:
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. at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error) at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() at System.Data.SqlClient.TdsParserStateObject.ReadBuffer() at System.Data.SqlClient.TdsParserStateObject.ReadByte() at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest) at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest) at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest) at System.Data.SqlClient.SqlDelegatedTransaction.SinglePhaseCommit(SinglePhaseEnlistment enlistment) --- End of inner exception stack trace --- at System.Transactions.TransactionStateInDoubt.EndCommit(InternalTransaction tx) at System.Transactions.CommittableTransaction.Commit() at System.Transactions.TransactionScope.InternalDispose() at System.Transactions.TransactionScope.Dispose()
有任何想法嗎? 為什么我會懷疑,當我得到它時我該怎么辦?
編輯以獲取更多信息
我實際上仍然沒有這個答案。 我所意識到的是,交易實際上是部分提交的。 一個表獲取插入但另一個表未獲得更新。 代碼是HEAVILY跟蹤,沒有太多空間讓我錯過一些東西。
有沒有辦法可以輕松找出交易是否已被提升。 我們可以從堆棧跟蹤中判斷它是否存在? 單一階段提交(在strack trace中)似乎表明沒有向我推廣,但也許我錯過了一些東西。 如果它沒有得到提升那么它怎么會有疑問。
這個難題的另一個有趣的部分是我創建了當前事務的克隆。 我這樣做是為了解決這個問題。 http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=914869&SiteID=1
不幸的是,我不知道這個問題是否已經解決。 也許創建克隆會導致問題。 這是相關的代碼
using (TransactionScope ts = new TransactionScope())
{
transactionCreated = true;
//part of the workarround for microsoft defect mentioned in the beginning of this class
Transaction txClone = Transaction.Current.Clone();
transactions[txClone] = txClone;
Transaction.Current.TransactionCompleted += new TransactionCompletedEventHandler(TransactionCompleted);
MyTrace.WriteLine("Transaction clone stored and attached to event");
m_dataProvider.PersistPackage(ControllerID, package);
MyTrace.WriteLine("Package persisted");
m_dataProvider.PersistTransmissionControllerStatus(this);
MyTrace.WriteLine("Transmission controlled updated");
ts.Complete();
}
謝謝
目前接受的答案是,非升級的LTM(非MSDTC)交易永遠不會有疑問。 經過對類似問題的大量研究后,我發現這是不正確的。
由於單階段提交協議的實現方式,在事務管理器將SinglePhaseCommit請求發送給其下級之后,以及在下級回復之前,事務處於“懷疑”狀態的時間很短。中止/或准備(需要推廣/升級到MSDTC)消息。 如果在此期間連接丟失,則事務處於“不確定”狀態,b / c當TransactionManager要求下屬執行SinglePhaseCommit時,它從未收到響應。
從MSDN單階段提交 ,還可以在此答案的底部看到“單階段提交流”圖像:
這種優化有一個可能的缺點:如果事務管理器在發送單階段提交請求之后但在接收結果通知之前失去與下級參與者的聯系,則它沒有可靠的機制來恢復事務的實際結果。 因此,事務管理器向等待信息結果通知的任何應用程序或選民發送In Inouboub結果
這里還有我發現的一些實際例子,它們會導致System.Transaction升級/升級到MSDTC事務(這與OP沒有直接關系,但我發現它非常有用。在VS 2013中測試過,SQL Server 2008 R2 ,.NET 4.5除非另有說明):
以下是導致升級的MS正式列表: http : //msdn.microsoft.com/en-us/library/ms229978( v = vs。85).aspx
答案是它不能。 顯然正在發生的是促銷活動正在進行中。 (我們意外地發現了這一點)我仍然不知道如何檢測促銷嘗試是否正在發生。 在檢測到這一點時,這本來就非常有用。
很難在沒有查看代碼的情況下給出任何建議,但我的第一個建議是,如果你有一個帶有1個連接的SQL服務器,則TransactionScope()是一個開銷。
為什么不使用System.Data.SqlClient.SqlTransaction()呢?
文檔sais“如果在數據庫事務中打開了與遠程服務器的連接,則與遠程服務器的連接將被登記到分布式事務中,並且本地事務將自動提升為分布式事務。” 但是,如果你真的只使用一個連接是一個非常奇怪的錯誤。 您確定沒有調用任何可以創建與MS SQL,MS MQ或其他需要創建分布式事務的連接的第三方組件嗎?
此外,如果您在SQL Server CLR過程中使用TransactionScope(),它將在任何情況下提升事務。
此外,如果您調用從鏈接的SQL服務器訪問表的存儲過程,我想這也需要升級。
這個問題已經很老了,也許你已經知道了答案,可以在這里發布給其他人。 謝謝!
打敗了我。
我習慣用“BEGIN TRANSACTION”和“COMMIT”或“ROLLBACK”手工執行ExecuteNonQuery。
很明顯,當一些代碼需要工作時,無論是否處於事務中,這都非常有效。
我實際上遇到了同樣的問題,它似乎與數據庫服務器的規格有關。 在執行此代碼時,我希望您的dba可以查看該框的CPU利用率。 這發生在我們的環境中,因為我們正在對事務中的數據庫中的大量行嘗試更新操作。 這種情況發生在我們最常用的表之一的OLTP數據庫上,這會產生鎖爭用。 我發現這個問題引人入勝的是我在堆棧跟蹤中看到的超時方面。 無論你設置的是什么超時值,無論是在命令上還是作為TransactionScope構造函數的參數,它似乎都沒有解決問題。 我要解決這個問題的方法是對提交進行分塊。 希望這可以幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.