首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

微軟工程師深度解析 SQL Server 阻塞與死結:成因、偵測與解決策略

     編輯:關於SqlServer

阻塞定義

連線 A 持有鎖,連線 B 請求相衝突的鎖類型 → B 等待 A 釋放鎖。阻塞可跨應用程式、跨用戶端發生。

五大常見阻塞情境

  1. 長時間執行查詢:大量 UPDATE/DELETE 取得大量鎖,甚至升級為資料表鎖。
    → 方案:優化索引、拆分大交易、離峰執行、隔離 OLTP/OLAP 工作負載。
  2. 不當使用游標:游標逐列處理慢於集合式操作,延長鎖持有時間。
    → 方案:改寫為集合式 SQL、若必須用游標設定 FAST_FORWARD、READ_ONLY。
  3. 取消查詢未提交/回滾:ODBC SQLCancel 僅取消陳述式,交易仍開啟,鎖保留。
    → 方案:應用程式必須在取消後明確呼叫 ROLLBACK 或 COMMIT。
  4. 應用程式未讀取完所有結果:結果集未耗盡 → 鎖保留於資料表。
    → 方案:立即讀取完畢或使用伺服器端游標;無法修改應用程式時,限制其僅存取報表/決策支援資料庫。
  5. 分散式用戶端/伺服器死結:單一用戶端開多連線非同步提交,SQL Server 無法自動偵測。
    → 方案:避免單一執行緒多連線非同步;使用繫結連接 (sp_getbindtoken/sp_bindsession) 協調。

避免阻塞的五項原則

  1. 設定查詢逾時 (Command Timeout)。
  2. 設定鎖逾時 (SET LOCK_TIMEOUT)。
  3. 善用繫結連接 協調多連線交易。
  4. 認清用戶端應用程式是鎖管理的真正主導者:查詢型態、結果處理方式直接決定鎖行為。
  5. 阻塞排查必須同時檢視 SQL 陳述式與應用程式行為 (連線管理、結果讀取、巢狀交易)。開發工具若不支援顯式控制,阻塞可能無解。

設計應用程式避免阻塞的準則

  • 縮短交易範圍:BEGIN TRAN 儘量晚開,COMMIT 儘量早關。
  • 避免使用者互動在交易中 (等待輸入導致鎖長時間持有)。
  • 使用 READ COMMITTED SNAPSHOT (RCSI) 或 SNAPSHOT 隔離等級,以版本存儲取代共享鎖,實現讀寫不阻塞 (需評估 tempdb 壓力)。
  • 大量異動採用分批提交,避免單一巨大交易。
  • 監控 sys.dm_exec_requests, sys.dm_tran_locks, sys.dm_os_waiting_tasks 即時偵測阻塞鏈。

結語

阻塞本質是資源爭用,解決之道在於縮短持有時間、降低衝突機率、提供替代路徑。DBA 需與開發人員共同審視應用程式邏輯,而非單純調整伺服器參數。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved