承上篇探討,確認 Key Hash Value (Lock Hash) 並非用於索引 Seek 定位,而是鎖管理子系統識別資源的雜湊值。本文深入解析鎖資源類型、Key Hash 產生演算法、SQL 2005/2012 版本差異與 %%lockres%% 虛擬欄位實戰。
| 資源類型 | 說明 | 是否使用 Key Hash |
|---|---|---|
| RID | Heap 資料列識別碼 (File:Page:Slot) | 否 |
| KEY | 索引鍵 (叢集/非叢集) | 是,Key Hash = Lock Hash |
| PAGE | 8KB 頁面 | 否 |
| OBJECT / TABLE | 整個資料表 | 否 |
| HOBT | Heap 或 B-Tree | 否 |
KEY 鎖 依賴 Key Hash Value (6 Bytes) 代表索引鍵,避免在鎖管理結構中儲存完整鍵值 (最長 900 Bytes),節省記憶體並加速雜湊表查找。
// C# 鎖模式
lock (syncObject) { /* critical section */ }
// syncObject 相當於 Key Hash Value:同一資源的所有執行緒共用同一雜湊值作為同步物件
DBCC PAGE 輸出的資料頁記錄中 不顯示 KeyHashValue (除非開啟追蹤旗標)。僅能透過 %%lockres%% 查詢。DBCC PAGE 直接顯示每筆記錄的 KeyHashValue = (xxxxxxxxxxxx),且 %%lockres%% 仍可用。-- 1. 虛擬欄位 %%lockres%% (所有版本通用)
SELECT %%lockres%% AS LockResource, *
FROM dbo.MyTable
WHERE ID = 123;
-- 結果範例:(8194443284a0) -- 6 Bytes 十六進位
-- 2. DBCC PAGE 直接觀察 (SQL 2012+)
DBCC TRACEON(3604, -1);
GO
DBCC PAGE('MyDB', 1, 126, 3); -- File 1, Page 126, Print Option 3 (詳細記錄)
GO
-- 輸出片段:
-- Slot 0 Offset 0x0 Length 0 ...
-- KeyHashValue = (8194443284a0) <-- 直接可見
sys.dm_os_wait_stats 中 LCK_M_* 等待,若異常偏高且無明顯邏輯衝突,可懷疑碰撞 (極罕見)。DBCC PAGE 或 %%lockres%% 觀察,利於鎖問題診斷。