Dot-Net

SQL Server 連接池沒有檢測到關閉的連接?

  • January 28, 2010

多年來,我在所有連接到 SQL 伺服器的 Web 應用程序上都遇到了非常奇怪的問題。

問題是,如果數據庫伺服器出現問題(伺服器重新啟動或其他問題),de Web 應用程序從那時起停止工作,即使數據庫伺服器還活著並且之後很好。

發生的情況是每個 ADO.NET 操作(ExecuteNonQuery、CreateReader、BeginTransaction、…)都失敗並出現InvalidOperationException:“無效操作。連接已關閉”。似乎對**SqlConnection.Open()**的呼叫從應用程序池中檢索了一個連接,該連接…已關閉!

根據文件,連接池應該自動從連接池中刪除切斷的連接,但顯然關閉的連接不被視為“切斷”,因此對**SqlConnection.Open()**的呼叫很高興返回一個關閉的連接,假設它是打開,沒有檢查這個。

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

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

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

     connection.Open();
  }

  // ...
}

這種解決方法現在似乎有效,但我覺得這樣做不舒服。

所以我的問題是:

  1. 為什麼**SqlConnection.Open()**從連接池返回關閉的連接?
  2. 我的解決方法有效嗎?
  3. 有沒有更好的方法來處理這個?

不久前我對連接池進行了一些類似的研究,原因略有不同,但希望會有一些用處。我發現的是:

  1. 即使您在程式碼中關閉了一個連接,它也會返回到池中,而實際上並沒有關閉連接 - 準備好進一步使用。
  2. 如果該連接被切斷(即 SQL Server 重新啟動),當連接從池中返回以供另一個呼叫者使用並且該呼叫者對其執行 .Open 時,當數據庫伺服器仍處於關閉狀態時它**不會出錯。**這是連接池性能優勢的一部分,因為它實際上並沒有返回到數據庫伺服器進行連接。
  3. 當您實際嘗試針對連接執行命令(例如 ExecuteNonQuery)時,它實際上會引發異常

連接會自動從池中刪除,我的發現是這通常發生在最後一次使用後的幾分鐘內。因此,這可能是一個時間問題 - 它們正在被清除,但不是在嘗試再次重用連接之前。

這些是我當時看過的一些文章:

Sql Server Google Group

Using Connection Pooling in ASP.NET

編輯:

壞連接永遠留在池中聽起來很奇怪 - 你確定它確實如此,而且不僅僅是多個壞連接嗎?如果您確定,那麼聽起來這些連接沒有在您的程式碼中正確釋放。是我不久前讀到的另一篇非常好的文章,上面寫著(引用):

自動沖洗連接

如果池連接保持“關閉但可重用”狀態 4 到 8 分鐘(隨機選擇的時間間隔),連接池機制將關閉物理連接並丟棄池連接。除非剩餘連接數大於為池配置的最小連接數(預設為 0)。請注意,連接必須已被應用程序關閉(並釋放回池中)才能自動釋放。如果您沒有在程式碼中關閉連接或孤立 Connection 對象,則池機制將什麼也不做。不,沒有 ConnectionString 參數可以更改超時值。

引用自:https://stackoverflow.com/questions/2154024