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

SQL Server NOLOCK 提升查詢效能實戰:原理、風險與最佳實踐

     編輯:關於SqlServer

痛點:大資料量查詢遭遇鎖定爭用

隨資料增長,查詢速度下降。建立索引是首選,但語法層面加上 WITH (NOLOCK) 可立即改善線上高併發環境下的鎖定爭用,顯著提升查詢吞吐量。

鎖爭用根因分析

鎖升級機制導致死鎖

SQL Server 採用混合鎖策略:起始用列鎖,隨修改行數增加升級為頁面鎖、表鎖。兩用戶以相反順序修改邏輯無關但物理相鄰的記錄,易觸發死鎖:

  1. 用戶 A 鎖定表 A 頁面(含大量無關行)
  2. 用戶 B 鎖定表 B 頁面(含用戶 A 需要的行)
  3. 雙方互相等待對方釋放鎖 → 死鎖

資料庫透過死鎖偵測犧牲修改量較小的交易,但頻繁死鎖嚴重影響系統穩定性。

NOLOCK 與 ROWLOCK 手動控制鎖粒度

NOLOCK:讀取不加鎖,犧牲一致性換取效能


SELECT COUNT(UserID) FROM Users WITH (NOLOCK) WHERE Username LIKE 'football%';
  • 優點:完全忽略共享鎖,避免封鎖與被封鎖,查詢效能大幅提升
  • 風險:髒讀——可能讀到未提交的交易資料,或讀取中途資料被修改導致不一致
  • 適用場景:報表查詢、統計分析、近似計算、資料品質容忍度高的場景

ROWLOCK:強制使用列鎖,避免頁面/表鎖升級


UPDATE Users WITH (ROWLOCK) SET Username = 'admin' WHERE Username = 'football';
  • 適用 SELECT、UPDATE、DELETE
  • 建議僅在 UPDATE/DELETE 且有明確主鍵條件時使用
  • 避免批次更新觸發頁面鎖升級

實測效能對比:1萬筆資料查詢

無 NOLOCK:34,720 ms

無 NOLOCK 耗時

加上 WITH (NOLOCK):2,563 ms

有 NOLOCK 耗時

效能提升約 13.5 倍(實際倍數視鎖爭用嚴重度而定)。

NOLOCK 寫法細節與版本差異

寫法適用版本指定索引跨伺服器查詢
WITH (NOLOCK)SQL 2005+容易搭配 INDEX()不支援,報錯
NOLOCK (無 WITH)所有版本較麻煩支援

跨伺服器範例:


-- 錯誤
SELECT * FROM [LinkedServer].db.dbo.table WITH (NOLOCK);

-- 正確
SELECT * FROM [LinkedServer].db.dbo.table NOLOCK;

最佳實踐建議

  1. 業務評估優先:確認業務可接受髒讀風險(如財務核對、庫存扣款嚴禁使用)
  2. 搭配隔離層級:SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 效果等同全查詢 NOLOCK
  3. 監控死鎖趨勢:NOLOCK 非萬靈丹,根治需優化索引、縮短交易、調整隔離層級
  4. 讀寫分離架構:報表查詢導向唯讀副本,從根源消除主庫查詢鎖爭用
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved