2010-01-28 153 views
18

多年來,我在連接到SQL服務器的所有Web應用程序中遇到了非常奇怪的問題。SQL Server連接池不檢測關閉的連接?

的問題是,如果事情發生在數據庫服務器(服務器重啓或其它問題),德web應用程序停止從該點工作,即使數據庫服務器是活得很好之後。

會發生什麼情況是,每一個ADO.NET操作(的ExecuteNonQuery,CreateReader,的BeginTransaction,...)失敗,出現InvalidOperationException異常: 「操作無效的連接被關閉」。看來,到SqlConnection.Open()的調用檢索來自應用程序池被關閉......連接!

根據該文件,連接池應自動刪除切斷連接池中的連接,但apparantly關閉的連接不被視爲「切斷」,所以調用SqlConnection.Open()愉快地返回關閉連接,假設它是打開的,而不檢查它。

我目前的解決辦法是打開後立即檢查連接的狀態:

using (SqlConnection connection = new SqlConnection(connectionString)) 
{ 
    connection.Open(); 

    if (connection.State != ConnectionState.Open) 
    { 
     SqlConnection.ClearAllPools(); 

     connection.Open(); 
    } 

    // ... 
} 

這種解決方法似乎對於現在的工作,但我不覺得舒服這樣做。

所以我的問題是:

  1. 爲什麼SqlConnection.Open()回報關閉連接池中的連接?
  2. 我的解決方法是否有效?
  3. 有沒有更好的方法來處理這個問題?

回答

12

我做了一些類似的研究,連接池前一陣子,一個稍微不同的原因,但希望會有些用處。我發現的是:

  1. 即使您關閉代碼中的連接,它也會返回到池中,但連接實際上未關閉 - 可供進一步使用。
  2. 如果連接被切斷(即SQL Server重新啓動),當連接從池返回供其他調用者使用並且該調用者執行打開操作時,它不會在該位置發生錯誤服務器仍然停機。這是連接池的性能優勢的一部分,因爲它實際上不會返回到數據庫服務器進行連接。
  3. 當您實際嘗試對連接執行命令時(例如,的ExecuteNonQuery)正是在這一點上,它實際上拋出一個異常

連接自動從池中刪除,我的調查結果,這通常發生在幾分鐘內它最後一次使用完。所以,這可能是一個計時問題 - 它們正在被清理,但不會在連接嘗試再次被重用之前。

這些都是一些文章我看了,當時:
Sql Server Google Group
Using Connection Pooling in ASP.NET

編輯:
這聽起來奇怪的是,糟糕的連接保持在池中永遠 - 你確定它肯定會這樣做,而且這不僅僅是多重不良連接?如果你確定,那麼這聽起來像這些連接沒有在你的代碼中正確釋放。 This是另一種非常好的文章我前一陣子看,上面寫着(報價):

自動沖洗連接

如果一個連接池保持在 「關閉,但可重複使用的」狀態 4至8分鐘(間隔 隨機選擇)連接 池化機制關閉物理 連接並丟棄彙集的 連接。也就是說,除非其餘連接的編號 大於爲池配置的最小連接數 (默認 爲0)的 。請注意,在 之前,連接必須 已被應用程序 關閉(並已釋放回池),因此可能會自動發佈 版本。如果您未關閉代碼中的 連接或孤立 連接對象,則共享 機制將不會執行任何操作。沒有, 沒有ConnectionString參數到 更改超時值。

+0

我可以忍受「幾分鐘」,但使用連接時,顯然會引發異常,但連接池中的「壞」連接永遠保持可用狀態。它永遠不會被刪除,儘管ADO.NET確實會拋出異常,因爲連接不好。 –

2

我們已經看到了從C同樣的問題++使用ADO。幾年前,在使用Microsoft支持之後,我們還在代碼中實現了類似的重試邏輯,並重置解決問題的連接池。

如果有一個更好的解決辦法,在微軟的鄉親支持要麼不知道,還是不共享(當時反正)。