SQL Server 預設隔離等級為 READ COMMITTED,透過共享鎖 (S) 保護讀取、排他鎖 (X) 保護寫入。但在特定業務場景 (報表唯讀、長交易一致性、避免死鎖、強制序列化) 需覆寫預設行為,SELECT ... FROM Table WITH (Hint) 即為此而生。
| 提示 | 全名 | 鎖類型與持有期 | 典型用途 | 風險/副作用 |
|---|---|---|---|---|
NOLOCK | 不加鎖 / READUNCOMMITTED | 不取得共享鎖,讀取未認可資料 (髒讀) | 報表查詢、資料探勘、可容忍不一致的大量掃描 | 髒讀、非重複讀、幻讀、可能讀到中斷交易的半寫入頁面 (601/602 錯誤) |
HOLDLOCK | 保持鎖 / SERIALIZABLE | 共享鎖持有至交易結束 (等同 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE) | 需在交易內多次讀取同一資料且要求完全一致 (如庫存扣款前複查) | 並發度極低、易造成封鎖/死鎖、索引範圍鎖 (Key-Range Lock) 開銷大 |
UPDLOCK | 更新鎖 | 讀取時取得更新鎖 (U),持有至交易/陳述式結束,轉 X 鎖時無衝突 | 「查詢-修改」模式:先讀取再決定是否更新,避免轉換死鎖 (S→X 衝突) | 降低並發、若未真正更新仍持有 U 鎖較久 |
TABLOCK | 表鎖 (共享) | 整張表共享鎖,持有至陳述式結束 | 大量載入前鎖定、報表需穩定快照且表較小 | 封鎖所有寫入、大表嚴重影響並發 |
PAGLOCK | 頁鎖 (共享) | 共享頁鎖 (預設行為之一) | 明確指定頁級粒度,避免升級為表鎖 | 較少直接指定,通常由最佳化器決定 |
TABLOCKX | 排他表鎖 | 整張表排他鎖 (X),持有至交易/陳述式結束 | 大量刪除/截斷前、DDL 維護窗口、單工模式匯入 | 完全封鎖所有存取、極高風險,僅限維護窗口 |
READPAST:跳過已鎖定列/頁,適用佇列處理 (如 DELETE TOP (100) FROM Queue WITH (READPAST) OUTPUT deleted.*)。ROWLOCK / PAGLOCK / TABLOCK:強制鎖粒度,配合 UPDLOCK/HOLDLOCK 使用。INDEX(index_name)、FORCESEEK:存取路徑提示,非鎖定提示但常搭配使用。SET TRANSACTION ISOLATION LEVEL,但 NOLOCK 不影響寫入鎖。SNAPSHOT 隔離等級 (RCSI) 取得陳述式/交易層級一致性且不封鎖寫入。sys.dm_tran_locks 觀察鎖升級 (Lock Escalation) 行為,必要時 ALTER TABLE ... SET (LOCK_ESCALATION = DISABLE/AUTO)。
-- 資料庫層級啟用 Read Committed Snapshot Isolation (RCSI)
ALTER DATABASE Db SET READ_COMMITTED_SNAPSHOT ON;
-- 或交易層級 Snapshot Isolation (SI)
ALTER DATABASE Db SET ALLOW_SNAPSHOT_ISOLATION ON;
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRAN; SELECT ...; COMMIT;
RCSI 讓 READ COMMITTED 讀取透過 tempdb 版本存儲取得一致性快照,**完全不取得共享鎖,寫入不封鎖讀取,讀取不封鎖寫入**,解決 90% 過去需 NOLOCK/HOLDLOCK 的場景,且無髒讀風險。