首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

SQL Server 查詢加 NOLOCK?一篇講清並發風險與正確用法

     編輯:關於.NET

專案中為追求查詢效能,開發者習慣在所有資料表後加 NOLOCK 或 WITH(NOLOCK)。這真的合適嗎?本文從並發存取問題、鎖機制、隔離層級深入分析,給出科學用法建議。

並發存取的三大經典問題

  • 髒讀:讀取到未提交的修改,後來該修改被回滾,導致讀到不存在的資料。
  • 不可重複讀:同一交易中兩次讀取同一筆資料,中間被其他交易修改,導致結果不一致。
  • 幻讀:同一查詢條件下兩次查詢,中間有資料新增/刪除,導致記錄筆數變化。

SQL Server 並發控制機制

鎖類型與模式

依資源粒度:表鎖、行鎖、頁鎖 (8KB)、檔案鎖、資料庫鎖。
依相容性:共享鎖 (S, 讀取)、更新鎖 (U, 預防死鎖)、排他鎖 (X, 寫入)。
程式設計師視角:樂觀鎖 (資料庫自管) vs 悲觀鎖 (程式手動控制)。

隔離層級控制鎖行為

隔離層級髒讀不可重複讀幻讀備註
Read Uncommitted✓✓✓等同 NOLOCK,效能最好,一致性最差
Read Committed✗✓✓SQL Server 預設
Repeatable Read✗✗✓
Serializable✗✗✗最高隔離,並發效能最低

NOLOCK 的代價與適用場景

NOLOCK = READ UNCOMMITTED,不發出共享鎖,允許髒讀。確實能提速,但犧牲資料正確性。

建議僅在以下場景謹慎使用:

  1. 資料量極大、查詢頻繁、可容忍髒讀的報表/統計類查詢;
  2. 業務邏輯允許髒讀(如非金融、非庫存核心數據);
  3. 資料極少修改的靜態參考表(省去鎖開銷)。

更好的替代方案:啟用資料列版本控制 (RCSI/Snapshot)

資料庫層級啟用 READ_COMMITTED_SNAPSHOT ON 或 ALLOW_SNAPSHOT_ISOLATION ON,讀取不阻塞寫入、寫入不阻塞讀取,統一解決並發衝突,避免到處撒 NOLOCK 的維護惡夢。這才是架構層面的正確解法。

小補充:NOLOCK vs WITH(NOLOCK)

  • SQL Server 2005+ 僅支援 WITH(NOLOCK) 語法;
  • WITH(NOLOCK) 更易搭配索引提示(如 WITH(NOLOCK, INDEX(idx_name)))。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved