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

SQL Server SELECT 語句鎖定提示 (Table Hints) 完整解析:NOLOCK、HOLDLOCK、UPDLOCK、TABLOCK、PAGLOCK、TABLOCKX

     編輯:關於SqlServer

SQL Server 提供豐富的鎖定提示,讓開發者在 SELECT 語句中精確控制並行存取行為。本文系統整理六大常用提示的行為、適用場景、風險與最佳實務,並說明其如何覆蓋交易隔離等級設定。

六大鎖定提示對照表

提示中文名鎖定類型持續時間典型用途風險/副作用
NOLOCK不加鎖 / 髒讀無鎖定 (Sch-S 除外)即時釋放報表查詢、資料探勘、可容忍髒讀讀到未認可資料、資料列可能消失/重複
HOLDLOCK保持鎖 / 序列化範圍共享鎖 (Range-S)交易結束需在交易中重複讀取相同資料、防止幻讀並行度降低、易死結
UPDLOCK更新鎖更新鎖 (U)交易/陳述式結束讀取後稍後更新同筆資料、防止轉換死結阻塞其他 U/X 鎖、需在交易中使用
TABLOCK表鎖 (共享)表級共享鎖 (Tab-S)陳述式結束大量讀取、配合 HOLDLOCK 達序列化阻塞所有寫入、大表影響面廣
PAGLOCK頁鎖 (預設)頁級共享鎖 (Pag-S)陳述式結束預設行為、平衡並行與開銷無特殊風險
TABLOCKX排他表鎖表級排他鎖 (Tab-X)交易/陳述式結束大量載入、重建索引、獨佔維護完全阻塞所有存取、極高衝突

語法範例

-- 單一提示
SELECT * FROM Orders WITH (NOLOCK) WHERE CustID = 1001;

-- 多重提示 (UPDLOCK + HOLDLOCK = 序列化讀取)
SELECT * FROM Accounts WITH (UPDLOCK, HOLDLOCK) WHERE AcctID = 500;

-- 結合索引提示
SELECT * FROM Orders WITH (NOLOCK, INDEX(IX_Orders_CustDate)) WHERE CustID = 1001;

關鍵行為補充

  • 覆蓋隔離等級:提示優先於 SET TRANSACTION ISOLATION LEVEL 與資料庫預設隔離等級。
  • NOLOCK ≠ 無任何鎖:仍會取得 Sch-S (結構穩定性) 鎖,防止 DDL 變更結構;不阻塞 DML,但 DDL 會阻塞 NOLOCK 查詢。
  • UPDLOCK 必須在交易中:單獨陳述式結束即釋放,失去保護更新意圖的效果。正確模式:BEGIN TRAN; SELECT ... WITH (UPDLOCK, HOLDLOCK); UPDATE ...; COMMIT;
  • TABLOCK + HOLDLOCK = 序列化:等同 SERIALIZABLE 隔離等級,防止幻讀。

最佳實務建議

  1. ✅ 報表/唯讀查詢:NOLOCK 或設定資料庫 READ_COMMITTED_SNAPSHOT ON (RCSI) 取得陳述式層級快照,無髒讀風險。
  2. ✅ 讀取後更新:UPDLOCK, HOLDLOCK 於同一交易內。
  3. ✅ 大量匯入/維護:TABLOCKX 獨佔表,搭配 BULK_LOGGED 復原模式。
  4. ❌ 避免在 OLTP 核心交易常態使用 NOLOCK,財務/庫存資料嚴禁。
  5. ❌ 避免常態使用 TABLOCK/TABLOCKX,除非經過負測驗證。

現代替代方案:快照隔離

-- 資料庫層級啟用 (需獨佔)
ALTER DATABASE YourDB SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE YourDB SET ALLOW_SNAPSHOT_ISOLATION ON;

-- 工作階段層級使用
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRAN; SELECT * FROM Orders; COMMIT;

RCSI/SI 提供無鎖定讀取且保證一致性,為現代 OLTP 首選架構。

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