阻塞定義
連線 A 持有鎖,連線 B 需相衝突的鎖 → **B 被迫等待 A 釋放**。跨應用、跨用戶端均可發生。
系統目錄表、索引鎖往往被忽視。長時間持鎖 → 阻塞鏈效應。
五大常見阻塞場景
- 長時間查詢: 大量
DELETE/UPDATE 獲取海量鎖(無論是否升級為表鎖)。
→ 優化查詢、調整索引、拆分複雜查詢、離峰/專機跑決策查詢。
- 不當使用游標: 游標逐列處理遠慢於集合操作。
→ 改用集合式 SQL。
- 取消查詢未提交/回滾:
SQLCancel 僅取消執行,**不自動回滾事務**,鎖保留。
→ 應用必須顯式 COMMIT/ROLLBACK 管理巢狀層級。
- 未提取所有結果列: 應用未讀完結果集 → 鎖殘留表上。
→ 應用必須立即讀取所有列;無法修改的工具限制用於報表/決策庫。
- 分散式客戶端/伺服器死鎖: 多連線非同步提交,應用阻塞在連線 A 等結果,連線 B 結果無人處理 → **SQL Server 無法自動偵測**。
→ 避免單執行緒多連線非同步模式;用綁定連接或查詢超時。
避免阻塞的核心方法
- 設定**查詢超時**與**鎖定超時**(
SET LOCK_TIMEOUT)。
- 使用**綁定連接**協調多連線事務。
- **核心認知:** SQL Server 是客戶端應用的「提線木偶」,鎖幾乎完全由客戶端查詢模式與結果處理決定。**解決阻塞必須檢視客戶端代碼**。
- 開發工具若不支援顯式連線管理、超時控制、結果處理 → 阻塞可能無解。
應用程式設計防阻塞準則
- 禁止讓用戶輸入觸發長查詢(如通配符、空白欄位查詢)。
- 禁止在事務中等待用戶輸入。
- 允許使用者取消查詢。
- 使用查詢/鎖定超時防失控查詢與分散式死鎖。
- **立即提取所有結果列**。
- 事務**盡可能短小**。
- 顯式控制連線管理(連線池、手動開關)。
- **全併發壓力測試**驗證上線前。