2011-06-15 94 views
32

我一直在爲此工作了大約一天半,並且搜索了大量的博客和幫助網絡上的文章。我發現了幾個與這個錯誤有關的問題,但我認爲它們不適用於我的情況(或者在某些情況下,不幸的是,我無法很好地理解它們來實現:P)。我不確定我能夠很好地描述這一點,以獲得幫助...但這裏有:「此SqlTransaction已完成;它不再可用。」...配置錯誤?

我們有一個.NET應用程序來跟蹤我們的資源。有一個導出功能可將資源複製到時間跟蹤系統和計費系統;這將訪問鏈接到時間和賬單數據庫的存儲過程。

我最近將計費系統數據庫移至新服務器(原始服務器:Server 2003 SP2,SQL 2005;新服務器:Server 2008 R2,SQL 2008 R2)。我有一個指向2008數據庫的鏈接服務器。我更新了存儲過程以指向2008服務器,然後出現了有關MSDTC和RPC的錯誤(http://www.safnet.com/writing/tech/archives/2007/06/server_myserver.html)。我在鏈接服務器上啓用'rpc/rpc out'並將MSDTC設置爲允許網絡訪問(如下所示:http://www.sqlwebpedia.com/content/msdtc-troubleshooting)。

現在我收到了上述內容,當我嘗試運行導出函數時:「此SqlTransaction已完成;它不再可用。」我覺得奇怪的是,當我剛剛運行存儲過程(來自SSMS)時,它說它已成功完成。

有沒有人見過這個?我錯過了配置中的某些東西嗎?我繼續瀏覽相同的頁面,我發現的唯一情況是在進行MSDTC更改後沒有重新啓動(在此提及:http://social.msdn.microsoft.com/forums/en-US/adodotnetdataproviders/thread/7172223f-acbe-4472-8cdf-feec80fd2e64/)。

我可以發佈部分或全部存儲過程,如果它會幫助...請讓我知道。

+0

http://stackoverflow.com/a/15923556/ 900284 – 2013-04-10 10:56:56

回答

31

我相信這個錯誤信息是由於「殭屍交易」。

查找可能發生的事務兩次(或回滾兩次,或回滾並提交等)的地方。 .Net代碼是否在SP已經提交之後提交事務? .Net代碼在遇到錯誤時是否回滾,然後嘗試在catch(或finally)子句中再次回滾它?

這可能是一個錯誤條件永遠不會在舊服務器上被擊中,因此錯誤的「雙滾回」代碼從未被擊中。也許現在你有一種情況,那裏新服務器上的一些配置錯誤,現在錯誤的代碼通過異常處理被擊中。

你可以調試到錯誤代碼?你有沒有堆棧跟蹤?

+2

看起來像是在正確的軌道上...我發現了另一個工具(dtctester),我原來的錯誤是由於配置錯誤(我以爲我檢查了新服務器上的防火牆...猜這就是我得到的假設)。看起來像我的新錯誤符合你的意思,「EXECUTE後的事務計數表示COMMIT或ROLLBACK TRANSACTION語句丟失。前一個計數= 1,當前計數= 2。」我將不得不多做一點挖掘並回復你。 – 2011-06-15 14:44:46

+2

我假設代碼中有重複的內容......我在存儲過程中註釋了回滾事務,它看起來像現在一切正常。我在等待用戶測試,但它已經超過了之前出現錯誤的地步。 :)感謝您的輸入! – 2011-06-15 15:03:25

3

我最近遇到過類似的情況。要在任何VS IDE版本中進行調試,請從調試(Ctrl + D,E)中打開異常 - 針對列「Thrown」檢查所有複選框,然後以調試模式運行應用程序。我意識到其中一個表沒有在新數據庫中正確導入,所以內部的Sql Exception導致連接中斷,從而導致這個錯誤。

故事的主旨在於,如果以前的工作代碼的新數據庫返回此錯誤,這可能是數據庫模式缺失問題,通過上述的調試尖端實現,

希望它能幫助, HydTechie

+0

感謝您的提示,通過一個真正的巴洛克式(車輪內輪子.....)傳統應用程序,這有助於縮小問題 – orgtigger 2014-05-28 16:47:30

4

最近,我在一個新的連接管理器中進行了重構之後,有了這個。一個新的例程接受一個事務,以便它可以作爲分批的一部分來運行,問題是與使用塊:

public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null) 
{ 
    using (transaction.Connection) 
    { 
    using (transaction) 
    { 
     return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure); 
    } 
    } 
} 

看起來好像外使用被關閉底層連接從而任何試圖提交或回滾交易拋出了消息"This SqlTransaction has completed; it is no longer usable."

我刪除了用戶添加了覆蓋測試,問題就消失了。

public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null) 
{ 
    return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure); 
} 

檢查任何可能在交易環境內關閉連接的情況。

2

在我的情況下,問題是包含在事務中的其中一個查詢引發了一個異常,並且即使異常處理「優雅」,它仍然設法回滾整個事務。

我的僞代碼就像:

var transaction = connection.BeginTransaction(); 
for(all the lines in a file) 
{ 
    try{ 
     InsertLineInTable(); // INSERT statement might fail and throw an exception 
    } 
    catch { 
     // notify the user about the error on line x and continue 
    } 
} 

// Commit and Rollback will fail if one of the queries 
// in InsertLineInTable threw an exception 
if(CheckTableForErrors()) 
{ 
    transaction.Commit(); 
} 
else 
{ 
    transaction.Rollback(); 
} 
1

我有同樣的問題。發生此錯誤是因爲連接池。當存在兩個或更多的用戶訪問系統時,連接池也重用連接和轉換。如果第一個用戶執行提交或回滾,則該事務不會長期可用。

+1

這似乎也是我的問題,因爲它只發生在多個用戶在應用程序中。任何想法如何解決這一問題? – boilers222 2017-01-24 13:50:06

0

這裏是檢測殭屍交易

SqlTransaction trans = connection.BeginTransaction(); 

//some db calls here 

if (trans.Connection != null) //Detecting zombie transaction 
{ 
    trans.Commit(); 
} 

的方式反編譯了的SqlTransaction類,你會看到下面的

public SqlConnection Connection 
{ 
    get 
    { 
    if (this.IsZombied) 
     return (SqlConnection) null; 
    return this._connection; 
    } 
} 

我注意到,如果連接被關閉,該transOP會變成殭屍,因此不能Commit。 對我而言,這是因爲我在finally塊中有Commit(),而連接在try塊中。這種安排導致連接被丟棄並被垃圾收集。相反,解決方法是將Commit放入try塊中。

1

同時檢查從.NET應用程序對數據庫執行的任何長時間運行的進程。例如,您可能呼叫的存儲過程或查詢沒有足夠的時間完成,可能會在日誌中顯示爲:

  • 執行超時已過期。 完成操作或服務器沒有響應之前超時的時間已過。

    • 此SqlTransaction已完成;它不再可用。

檢查命令超時設置 嘗試運行跟蹤(探查),看看是什麼在DB側發生......

相關問題