首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

SQL 查詢死鎖快速緩解:WITH (NOLOCK) 使用指南

     編輯:MySQL 資料庫相關知識

現象

高併發讀寫場景下,SELECT 被寫入交易阻塞,甚至觸發死鎖(Error 1205),導致查詢中斷。

最簡單緩解:NOLOCK 提示

SELECT au_lname
FROM authors WITH (NOLOCK);

等價於設定交易隔離等級 READ UNCOMMITTED,讀取時不申請共享鎖,直接讀取資料頁當前版本(含未提交資料)。

優缺點權衡

優點缺點/風險
完全不阻塞寫入,查詢極快 可能讀到「髒資料」(未提交/已回滾的資料)
不持有鎖,減少死鎖機率 可能出現「幻讀」或「不可重複讀」
語法簡單,無需改應用邏輯 索引掃描時可能遇到頁分裂導致錯誤 601

適用場景

  • 報表、儀表板、非關鍵業務查詢,可容忍極小概率髒讀。
  • 資料倉庫唯讀副本查詢。
  • 臨時排查死鎖,作為短期止血方案。

更穩健的替代方案

  1. 啟用 READ_COMMITTED_SNAPSHOT (RCSI):資料庫層級設定 ALTER DATABASE db SET READ_COMMITTED_SNAPSHOT ON,讀寫不再互相阻塞,語意上保證語句級一致性。
  2. 快照隔離 (SI):SET TRANSACTION ISOLATION LEVEL SNAPSHOT,需應用程式顯式開啟交易,適合長交易一致性讀。
  3. 索引優化:減少掃描範圍、避免鍵值查詢,從根源降低鎖爭用。
  4. 應用層重試邏輯:捕捉 1205 錯誤碼,指數退避重試 2-3 次。

最佳實踐建議

預設開啟 RCSI,僅在極少數「寧可髒讀不可阻塞」的報表查詢上加 WITH (NOLOCK),並在程式碼註解標註風險承擔者。

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