使用者通報某網頁無法開啟,錯誤訊息為 SQL 查詢發生 Timeout,由錯誤行數推論查詢指令為單純的 SELECT * FROM MyTable WHERE PK = @id。進一步測試並確認問題只出在 MyTable 特定一筆,@id 換成其他值就是正常的。還有一點奇怪的地方,另一個網頁也是查詢 MyTable 卻能正常查詢及顯示該筆資料不會 Timeout,探究其差異在於異常 SELECT 包含了兩個型別為 NTEXT 欄位。

依據前述線索,我推測最可能的原因是該筆資料被某個未 Commit 或 Rollback 的交易鎖定,導致查詢被阻擋而等待逾時。

請 DBA 協助調查,直接在 SSMS 執行 SELECT * FROM MyTable WHERE PK = @id 也會卡住無回應,甚至無法取消害 SSMS 必須用工作管理員才能關掉。重開 SSMS 並重跑測試,觀察各工作階段的狀態,查出 SELECT * FROM MyTable WHERE PK = @id 是被另一個在執行 sp_releaseschemablock 的工作階段 Block,將該工作階段砍掉問題即告排除,原本 Timeout 的網頁恢復正常。

所以這場詭異的 Blocking 是我沒聽過的 SP - sp_releaseschemablock 所引起的。

爬文探了底細,網路上有不少人提到 sp_releaseschemablock 跟 Blocking 有關聯。

彙整相關討論,我的心得如下:

  1. sp_releaseschemablock 屬於 Undocumented External Procedure,多為 SQL 內部用於明確釋放鎖定,一般開發人員不太用得到。
  2. sp_releaseschemablock 常與 Block、MSDTC、Linked Server 等關鍵字一起出現。
  3. 雖然 sp_releasschmablock 常出現在肇事現場,成為 Blocking 工作階段殘留的執行指令而被當成頭號嫌犯,但它多半是無辜的。實際狀況往往是該工作階段執行了 sp_getschemalock 加上鎖定、進行資料操作,最後執行 sp_releaseschemablock 釋放鎖定,過程出了差錯殘留鎖定且工作階段也沒關閉。但前面的指令已消失不可考,留下 sp_releaseschemablock 傻傻站在現場被當現行犯。

結論:sp_releaseschemablock 本身是無辜的,它其實被按排在一連串資料庫存取動作後負責釋放鎖定。當鎖定作業出現瑕疵未釋且工作階段殘留,sp_releaseschemablock 很容易就變成代罪羔羊。至於真正造成問題的指令,就像這次遇到的案例,往往已不可考。謎團未解,但學到了經驗。

Case of SQL blocking caused by 'sp_releaseschemablock'.


Comments

# by Huang

請換成Oracle DB,天下太平

# by paiyuliu

Oracle沒有Lock問題嗎?

Post a comment