為什麼sleeping的會話會造成阻塞

z_cloud_for_SQL發表於2023-02-15

背景

客戶反映HIS資料庫每天22點後都會發生阻塞,阻塞的源頭是一個sleeping的會話,越阻塞越多,只能透過手動KILL掉才能解決,十分不解為什麼狀態為sleeping的會話會造成阻塞。

現象

在SQL專家雲的活動會話中,回溯22點一個小時內的執行情況,從22點開始出現阻塞情況。

轉到活動會話原始資料,看到ID為2661的會話是阻塞源頭,且狀態為sleeping。

檢視2661的完整資訊,發現該會話中有3個開啟的事務,一直沒有關閉,開啟事務的時間為22:00。

再轉到22:00的活動會話原始資料,發現會話2661被會話615阻塞。當時2661正在執行到一個儲存過程的UPDATE語句。

在慢語句中找到會話2661,執行時間為30秒多一點。向客戶證實,程式上設定的SQL語句的超時時間為30秒,說明2661被阻塞導致超時了。

會話615是一個作業,22點開始執行,執行時間91秒。

 

分析

透過回溯,很容易分析阻塞的原因,首先22:00執行的作業會話615阻塞了會話2661,當時會話2661正在執行的SQL語句為儲存過程中的語句update yz_zy_patient。

透過儲存過程的定義可以看到,會話2661在被阻塞之前,已經執行完了begin tran和update mz_charge_detail語句。

 

因為會話2661一直被阻塞,直到30秒後超時,所以不會執行到下面的COMMIT語句。最重要的是,應用程式實現的不健壯,語句超時報錯後沒有進行錯誤處理,回滾事務並關閉連線(會話),導致會話2661變成了一個“殭屍”會話。因為沒有處理事務,會話2661一直持有對錶mz_charge_detail更改的資料行的排他鎖,其他會話在對錶mz_charge_detail進行更新時就會被一直阻塞。

解決

  1. 修改應用程式,增加對執行異常的捕獲,回滾事務並關閉連線。這是最根本的解決辦法。
  2. 修改儲存過程,在事務開始之前增加SET XACT_ABORT ON語句,當 SET XACT_ABORT 為 ON 時,如果 SQL 語句產生執行時錯誤,整個事務將自動終止並回滾。在修改應用程式之前作為臨時解決辦法。

自動查殺會話

sleeping會話導致阻塞是一個非常普遍的問題,因為很多客戶是購買軟體廠商的產品,修改程式的根本解決辦法不容易落實。因此只能在資料庫端進行補償性的措施,就是配置一個自動查殺會話的作業,根據這種會話的特徵定期KILL掉。也可以在SQL專家雲中啟用自動查殺會話的功能。

 

 

 

相關文章