背景
我在處理客戶問題的時候,客戶經常搞不懂sleeping 的由來,和他可能導致的問題。下面來詳細說下
什么是sleeping
其實我們經常可以在數據庫中看到“”sleeping“狀態的連接,但是這個sleeping 的狀態是怎么來的,如果有很多sleeping狀態的連接對數據庫有什么影響嗎?sleeping 代表建立了數據庫連接,但是,程序段沒有發出SQL命令. 因為很多應用程序為了減少打開和關閉連接的開銷,在完成數據庫中的操作后,仍然保持數據庫的連接。這些連接最主要的目的是重用。舉例:如果一個應用程序使用數據庫連接提取數據,如果已經存在一個連接可以重用,那么建立連接的消耗當然能夠最小化。那么,維護大量的sleeping連接會是一種開銷嗎?雖然,它相對來說是比較低的,但的確也是有開銷的。如果代碼編寫的合適,我們不應該看到大量的sleeping連接。
舉個栗子
新建一個控制台應用程序,先加入下面的代碼
1.建立連接並打開
SqlConnection sqlConnection = new SqlConnection("Server=(local);Database=Mydb;UId=test;Pwd=password;"); sqlConnection.Open();
查看數據庫會看到,此時就會出現SLEEPING狀態。這就是建立了連接但是沒有發出任何SQL命令
2.SQL執行語句完成
我們執行下面的代碼 。在執行的過程中可能有(running,suspened,runnale狀態)等他執行完。查看數據庫中的狀態變為sleeping.
SqlCommand sqlCommand = new SqlCommand("select name from dbo.Student", sqlConnection); sqlCommand.ExecuteScalar();
問題
到目前為止,sleepig是怎么來的應該很清楚了,,但他可能到導致的問題是什么呢。具體看下面案例,
會話77就是sleeping操作,他阻塞了會話81,81又阻塞了75. 看看等待時間,,有點不忍直視了,數學好的同學可以數一下。
這個問題怎么產生的呢? 其實就是在運行 sqlCommand.ExecuteScalar(); 的時候開啟了事務,但是這個語句由於超時或者查詢被取消了,會話變成了sleeping狀態。但是事務在數據庫中中還是開啟的狀態。
解決
通過查看上面圖中的工具,查看77 執行的語句,定位對應到程序中的代碼段,然后進行下面的改善措施:
1.在代碼中加入try catch的異常處理,在處理的的代碼中加入 :IF @@TRANCOUNT > 0 ROLLBACK TRAN
2.找到對應的執行的SQL,找出他執行超時的原因加以解決。
3.使用 SET XACT_ABORT ON; 他表示 如果執行 Transact-SQL 語句產生運行時錯誤,則整個事務將終止並回滾。