2012-03-20 77 views
4

假設我們正在執行大量不同的sql命令,並且SqlCommand.CommandTimeout的默認值爲30秒。.net SqlCommandTimeOut和連接池

讓我們假設其中一些sql命令只是長查詢,我們可能會得到超時異常。

糾正我,如果我錯了,這個異常只是原因.Net不想再等待,但如果我們使用連接池,這個連接可能保持打開,所以這個sql語句可能仍然運行SQL服務器端?或者在這些系統之間存在一些隱藏的通信,無論我們是否使用連接池,突然停止它?

只是想知道什麼是機制,它會影響SQL服務器的性能。我的意思是,如果查詢是非常長的,例如運行10分鐘,如果它仍在運行,它可能會減慢服務器的速度,因爲沒有人可以得到結果。

UPDATE

所以在這裏我想諮詢一下具體的連接池,它肯定,代碼將關閉與異常處理的連接,或者我們可以姑且認爲是使用代碼是首選模式在這裏由@dash命名。問題在於,如果我在該SqlConnection對象上調用Close()或Dispose()方法,它將返回到連接池,並不會在物理上關閉它。

我在問什麼時候它返回到池中,這個長查詢是否仍然在SQL Server端運行。如果可能的話,如何避免這種情況。

再次更新

感謝@dash提的是,關於數據庫事務,是回滾將使等待,我們沒有關閉連接,並將其返回到池中呢。那麼,如果它只是一個長選擇查詢或更新,而只是一個單獨的更新而沒有涉及任何數據庫事務呢?具體而言,我想知道是否有一種方法可以告訴SQL Server我現在不需要結果了,請停止運行它?

+1

否;沒有辦法 - 你可以殺死SQL Server上的正在運行的進程,但是你真的只需要讓SQL Server管理它正在做的事情。與所有情況一樣,如果您選擇運行降低服務器性能的查詢,那麼您可以選擇:-) – dash 2012-03-20 10:23:25

+0

您可以使用SQL KILL命令終止SQL Server上正在運行的進程。 KILL SPID並獲得SPID,您可以使用SELECT @@ SPID或從一個sys表中獲取所有當前進程。 – 2012-03-28 14:40:15

回答

5

這一切都取決於你如何執行你的查詢真的;

想象一下下面的查詢:

SqlConnection myConnection = new SqlConnection("connection_string"); 

SqlCommand myCommand = new SqlCommand(); 
myCommand.Connection = myConnection; 
myCommand.CommandType = CommandType.StoredProcedure; 
myCommand.CommandTimeout = some_long_time; 
myCommand.CommandText = "database_killing_procedure_lol"; 

myConnection.Open() //Connection's now open 

myCommand.ExecuteNonQuery(); 

會發生兩兩件事;一種是這種方法將排隊,直到command.ExecuteNonQuery()完成。第二個是,我們還將在該方法期間綁定來自連接池的連接。

如果我們超時會發生什麼?那麼拋出一個異常 - 一個Number屬性= -2的SqlException。但是,請記住,在上面的代碼中,沒有異常管理,因此所有將發生的事情是對象將超出範圍,我們需要等待它們被丟棄。特別是,我們的連接不會重複使用,直到發生這種情況。

這就是爲什麼以下方式是優選的,原因之一:

using(SqlConnection myConnection = new SqlConnection("connection_string")) 
{ 
    using(SqlCommand myCommand = new SqlCommand()) 
    { 

     SqlCommand myCommand = new SqlCommand(); 
     myCommand.Connection = myConnection; 
     myCommand.CommandType = CommandType.StoredProcedure; 
     myCommand.CommandTimeout = some_long_time; 
     myCommand.CommandText = "database_killing_procedure_lol"; 

     myConnection.Open() //Connection's now open 

     myCommand.ExecuteNonQuery();  

    } 

} 

這意味着,一旦查詢完成,無論是自然(它運行到完成),或通過一個異常(超時或否則),資源立即返回

在您的特定問題中,由於很多原因,執行大量查詢需要很長時間才能執行。在Web應用程序中,您可能會有許多用戶爭用有限數量的資源;內存,數據庫連接,CPU時間等等。因此,將這些與昂貴的操作綁定在一起會降低您的Web應用程序的響應能力和性能,或限制您可以同時使用的用戶數量。此外,如果數據庫操作昂貴,則可能會捆綁數據庫,從而進一步限制性能。

因爲這個原因,試圖爲數據庫查詢帶來執行時間總是值得的。如果你不能,那麼你必須小心你可以同時運行多少種類型的查詢。

編輯:

那麼,你是在什麼在SQL Server端真正感興趣...答案是...它取決於! CommandTimeout實際上是一個客戶端事件 - 你所說的是,如果查詢花費的時間超過了n秒,那麼我不想再等了。 SQL Server被告知這種情況,但它仍然需要處理它當前正在做什麼,所以在SQL Server完成查詢之前實際上可能需要一些時間。它會試圖優先考慮這一點,但就是這樣。

對於交易尤其如此;如果您正在運行包含在事務中的查詢,並且將其作爲異常管理的一部分回滾,那麼您必須等到回滾完成。

看到人們出現恐慌,並開始發出KILL命令來對照正在運行該查詢的SQL進程標識也很常見。如果命令運行一個事務,這通常是一個錯誤,但對於長時間運行的選擇通常是可以的。

SQL Server必須管理它的狀態,使其保持一致。客戶端不再監聽的事實意味着你已經浪費了工作,但SQL Server仍然必須自行清理。

所以,事物的ASP.Net一切都會好起來的,因爲它並不關心,但SQL Server仍然必須完成它開始的工作,或者達到可以放心安全工作的地步,或者回滾已打開的任何事務中的任何更改。

這顯然可能會對數據庫服務器產生性能影響,具體取決於查詢!

即使是長時間運行的SELECT或UPDATE或INSERT以外的事務也必須完成。 SQL Server會嘗試儘快放棄它,但前提是安全。顯然,對於UPDATES和INSERT尤其是,它必須達到數據庫仍然一致的地步。對於SELECT,它會嘗試儘快結束。

+0

對不起,我不清楚我的問題,我在詢問連接池,但沒有更好地練習'使用'關鍵字,請檢查我更新的問題。 – 2012-03-20 09:40:42

+0

這是一回事。如果你在完成這些連接後不立即釋放連接,那麼它們將不會在連接池中重用,直到它們被丟棄。該示例突出顯示了您可能無意中持續保持連接的時間超出了您的預期。最後一部分討論您執行許多長時間運行的查詢時可能遇到的性能問題。 – dash 2012-03-20 09:42:33

+0

嘿,我只是更新我的問題,請檢查,我真的問了一個不同的問題,這是我關閉連接,它返回到連接池,它仍然會在SQL服務器端運行。我不問.net如何處理連接池。謝謝 – 2012-03-20 09:47:27

0

感謝@dash提的是,關於數據庫事務,是一個 回滾將使等待,我們不關閉連接和 它返回到池中呢。那麼,如果它只是一個長選擇查詢或 更新,而只是一個單獨更新而沒有涉及任何數據庫 交易?並且具體是我想知道有沒有辦法可以告訴SQL Server我現在不需要結果 請問 停止運行了嗎?

我認爲這個鏈接將回答需要 Link1 Link2

+0

請注意文檔 - 「試圖取消執行一個SqlCommand」 - 操作詞是「試」 - 這是不能保證,我'我害怕。 – dash 2012-03-29 07:50:31