今天遇到一個很奇怪的情況,發現一個會話異常,這個會話只是在執行一個簡單的存儲過程,裡面使用了鏈接伺服器(Linked Server)查詢另外一臺伺服器數據(存儲過程裡面沒有任何顯性事務、UPDATE、DELETE操作,只有幾個簡單的SELECT查詢,其中有兩個查詢使用了鏈接伺服器Linked Ser... ...
今天遇到一個很奇怪的情況,發現一個會話異常,這個會話只是在執行一個簡單的存儲過程,裡面使用了鏈接伺服器(Linked Server)查詢另外一臺伺服器數據(存儲過程裡面沒有任何顯性事務、UPDATE、DELETE操作,只有幾個簡單的SELECT查詢,其中有兩個查詢使用了鏈接伺服器Linked Server,由於生產環境,不好貼出SQL語句),在DPA監控工具裡面,發現該會話引起了非常長的OLEDB等待時間,手工執行測試,發現並不耗費很長時間,KILL該會話後, 回滾狀態已完成一直是0%, 估計剩餘時間也一直是0秒。如下截圖所示:
KILL 129 WITH STATUSONLY;
SPID 129: 正在進行事務回滾。估計回滾已完成: 0%。估計剩餘時間: 0 秒。
如下所示,這個會話的start_time(Timestamp when the request arrived. Is not nullable.)為2016-10-18 02:17:58.210,到現在2016-10-19 16:02:30.173已經有幾十個小時了,我kill會話的時間點為2016-10-19 12:00:01。
可以看到它的等待類型是OLEDB等待(圖一),也就是說等待鏈接伺服器所指的伺服器返回結果。另外這個事務的transaction_type為2,意味這隻是一個Read-only transaction(避免別人誤解,這是一個證據),transaction_state為2,表示事務處於活動狀態(The transaction is active)。事務出現的這個時間點引起了我的註意,因為鏈接伺服器所指向的這台伺服器出現宕機(參考鏈接VmWare平臺Windows Server 2012 無響應宕機),剛好是那台伺服器虛擬機出現宕機時候,重啟的時間點前面一點(那台伺服器凌晨1點多宕機,2:22AM的時候重啟的)。從DPA監控工具也能看到確實是那個點出現的。如下所示:
這種分散式查詢,由於Linked Server所指的伺服器出現異常(例如宕機),這邊的會話進程一直在等待其返回結果,但是Linked Server所指伺服器由於異常永遠都無法給這個會話進程反饋任何結果,就出現了這種情況,不過有點奇怪的是,這種情況無法通過KILL會話來結束。 只能通過重啟伺服器來解決問題, 也不能通過Kill進程解決(因為SQL Server是單進程多線程架構,不像ORACLE那種多進程架構,可以從操作系統層面殺掉進程或線程(Windows平臺,Oracle提供了一個工具ORAKILL utility 可以Kill線程)),但是重啟資料庫是一個很麻煩的事情。 所以這個僵屍會話就一直存在資料庫裡面,對於我這個有強迫症的人,看著它的存在,總想幹掉它. 確實是個折磨人的事情.