由于在數據庫連接部分,新建連接的時候一直報“出錯原因:超時時間已到。超時時間已到,但是尚未從池中獲取連接。出現這種情況可能是因為所有池連接均在使用,并且達到了最大池大小。”于是,我便想查看一下數據庫的活動連接,看看究竟是哪個程序占用了過多的數據庫連接。
我們可以用sp_who(或sp_who2)來顯示所有活動的連接。
USE master; GO EXEC sp_who2; GO
查詢的結果如表1。為了可讀性,表1中的結果有刪減了一些列和一些行。但刪去的內容不影響我們要講的東西。
表1 sp_who2查詢的結果
從表1中,我們可以看到有很多進程狀態(見Status列)顯示sleeping,并且當前正在執行的命令類型(見Command)顯示AWATING COMMAND。
我們就有疑問,為什么有這么多的連接進程。首先,我們要明確一個概念,SQL Server 不會建立任何連接池,ADO.Net會。當我們在C#代碼中打開一個數據庫連接后,如果是首次連接,SqlClient就會打開一個SQL Server的連接。當我們從程序里面關閉這個連接時,SqlClient并不是真正地關閉了這個數據庫的連接,而是延后一段時間才關閉,默認是60秒。如果你沒有在指定延時內重新連接,SqlClient就真正地關閉這個連接。但如果你重連接了,SqlClient就會重用這個連接。這樣子,我們就可以使用相同的連接屬性。
但是有幾種可能的情況可能導致失敗,也就是連接不能重用(或在指定的時間內沒有關閉)。比如當你使用ExecuteReader的時候,沒有成功地取回所有的行和結果集,繼而在連接上沒有將reader關閉,可能導致這個問題。
常用的排查數據庫連接問題的方法是運行SQL Server Profiler(使用默認模板)。如果你看到一個Audit Login事件,就說明有一個新的連接已經被建立。如果你看到event RPC:Completed with the text "sp_reset_connection",這說明在連接池中的一個連接被重用。如果你一直沒有看到任何的sp_reset_connection,那就意味著你遇到問題了。SQL Server Profiler如圖1所示。
圖1 SQL Server Profiler
補充知識:
sp_who和 sp_who2的區別
sp_who是官方支持的,有文檔可查。sp_who2不是官方支持的,查不到對應的文檔,但它更常被使用。他們返回相同的信息:提供有關 Microsoft SQL Server 數據庫引擎實例中的當前用戶、會話和進程的信息。但是sp_who2額外添加了一些sp_who沒有提供的列。并且,sp_who2中的信息更緊湊,更適合用文本來顯示。Kalman 寫道:它增加了額外的spid列來增加結果的可讀性.
后記:
”超時時間已到。超時時間已到,但是尚未從池中獲取連接。出現這種情況可能是因為所有池連接均在使用,并且達到了最大池大小" 這個問題可能是進行查詢的時候,沒有成功的查詢造成的。比如說執行存儲過程的時候,原來需要提供給存儲過程3個參數,但你只提供了兩個,這就會導致查詢出現錯誤。當錯誤發生的時候,原先的數據庫連接就不能成功被釋放或重用,這就導致了ADO.Net要繼續創建新的數據庫連接,最終導致了線程池中達到了池本身能夠容納的指定連接數,最終導致新的連接不能繼續在線程池中創建。
參考鏈接:
SQL Server Profiler使用方法
文章列表