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

應用程式設計避免 SQL Server 阻塞的八大鐵律

     編輯:關於SqlServer

阻塞 是 SQL Server 併發環境的頭號效能殺手。當連線 A 持有鎖,連線 B 請求相衝突的鎖類型時,B 將被迫等待。絕大多數嚴重阻塞源於 **應用程式設計缺陷** 而非資料庫本身。本文提煉八大設計鐵律,從源頭杜絕阻塞。

鐵律一:拒絕長時間運行的查詢混入 OLTP

  • 現象: 大量刪除/更新、複雜報表查詢持有大量鎖,甚至升級為表鎖,封鎖高併發 OLTP。
  • 對策:
    • 物理隔離:報表/分析查詢導向唯讀複本 (AlwaysOn 可讀次要、還原備份、ETL 至數據倉庫)
    • 查詢優化:建立覆蓋索引、拆分大查詢、使用分頁、避免 SELECT *
    • 游標改寫:集合式操作 (JOIN/EXISTS/窗口函數) 替代逐列游標,效能常提升 10-100 倍

鐵律二:取消查詢必須配套 ROLLBACK/COMMIT

  • 現象: 應用呼叫 SqlCommand.Cancel() 或 ODBC SQLCancel() 後,未發送 ROLLBACK,交易保持開啟,鎖持續佔有。
  • 對策:
    • 客戶端程式碼 必須 在 catch/finally 區塊顯式 ROLLBACK (或 COMMIT)
    • 連線池機制:SqlConnection.Close() 會自動回滾未完成交易,確保正確使用 using 區塊
    • 監控:sys.dm_tran_active_transactions 定期檢查長時間閒置交易

鐵律三:務必讀取完所有結果集

  • 現象: 應用執行查詢後僅讀取前幾列就關閉 DataReader,剩餘結果集未讀取,導致共享鎖 (S 鎖) 持有到連線重置。
  • 對策:
    • 循環 while (reader.Read()) 讀取至結尾
    • 或使用 DataAdapter.Fill(DataTable) 一次性載入
    • 若框架不支援 (如舊版報表工具),將該應用隔離至專用唯讀複本

鐵律四:交易越短越好,嚴禁使用者互動在交易中

  • 現象: 交易開啟後等待使用者輸入 (彈窗確認、Web 頁面停留),鎖持有時間以「分鐘/小時」計算。
  • 對策:
    • 所有輸入參數在 BEGIN TRAN 前蒐集完畢
    • Web 應用採用「樂觀併發」:讀取時記錄版本號/時間戳,更新時 WHERE Version = @OldVersion
    • 批次作業拆分為多個微交易,每筆提交

鐵律五:合理設計索引,減少不必要的鎖升級

  • 缺少適當索引 → 掃描大量列 → 鎖升級為表鎖 (Tab Lock) → 全表封鎖
  • 為 WHERE/JOIN/ORDER BY 欄位建立索引,實現精準鎖定 (Key/Row Lock)
  • 避免過寬索引鍵,增加非叢集索引大小與鎖記憶體開銷

鐵律六:謹慎使用隔離等級,預設 READ COMMITTED 通常最佳

  • SERIALIZABLE / REPEATABLE READ: 持有共享鎖至交易結束,極易阻塞,僅用於極少數嚴格一致性場景
  • READ UNCOMMITTED (NOLOCK): 髒讀風險,不可用於財務/庫存等關鍵業務
  • READ COMMITTED SNAPSHOT (RCSI): **強烈推薦** 開啟資料庫選項 ALTER DATABASE SET READ_COMMITTED_SNAPSHOT ON,讀寫不阻塞,語句級一致性,零代碼修改

鐵律七:避免 IN/OR 子句導致計畫失效與鎖升級

  • 大量 IN 清單、OR 條件常導致優化器選擇掃描而非尋找
  • 拆分為多個簡單查詢,或使用暫存表/TVP JOIN
  • 必要時加入 OPTION (RECOMPILE) 獲取參數化計畫

鐵律八:監控與告警機制常態化

  • 部署 sp_WhoIsActive、Blocked Process Report (Trace Flag 1222/Extended Events) 自動捕獲阻塞鏈
  • 關鍵指標告警:Lock Wait Time > 5s、Blocking Chain Length > 3、Deadlocks/sec > 0
  • 建立阻塞知識庫:記錄每次阻塞的 SQL、執行計畫、應用呼叫堆疊、解決方案,沉澱組織經驗

總結:阻塞治理 = 索引優化 + 交易縮短 + 隔離等級選對 + 監控到位

將這八大鐵律納入開發規範、代碼審查清單、上線檢查表,可從根本上消除 90% 以上的應用層阻塞問題。

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