為什麼這個 RX-X 鎖沒有出現在擴展事件中?
問題
我有一對查詢,在可序列化的隔離下,會導致 RX-X 鎖定。但是,當我使用擴展事件觀看鎖獲取時,RX-X 鎖獲取永遠不會出現,它只是被釋放。它從何而來?
複製品
這是我的桌子:
CREATE TABLE dbo.LockTest ( ID int identity, Junk char(4) ) CREATE CLUSTERED INDEX CX_LockTest --not unique! ON dbo.LockTest(ID) --preload some rows INSERT dbo.LockTest VALUES ('data'),('data'),('data')
這是我的問題批次:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRAN INSERT dbo.LockTest VALUES ('bleh') SELECT * FROM dbo.LockTest WHERE ID = SCOPE_IDENTITY() --ROLLBACK
我檢查了這個會話持有的鎖,並查看了 RX-X:
SELECT resource_type, request_mode, request_status, resource_description FROM sys.dm_tran_locks WHERE request_session_id = 72 --change SPID!
lock_acquired
但我在和上也有一個擴展事件lock_released
。我在適當的 associated_object_id 上對其進行過濾……沒有 RX-X。執行回滾後,我看到 RX-X (LAST_MODE) 已釋放,即使它從未被獲取。
我試過的
- 我查看了擴展事件中的*所有鎖 - 沒有過濾。*未獲得 RX-X 鎖。
- 我也嘗試了 Profiler: 相同的結果(當然除了它的名字是正確的……沒有“LAST_MODE”)。
- 我執行 XE 進行鎖定升級 - 它不存在。
- 沒有專門用於轉換的 XE,但我能夠確認至少 U 到 X 鎖定轉換是由
lock_acquired
另外值得注意的是被收購但從未發布的 RI-N。我目前的假設是 RX-X 是轉換鎖,如此處所述。我的批次中有重疊的鍵範圍鎖,看起來它們應該有資格進行轉換,但 RX-X 鎖不在轉換錶中。
這個鎖是從哪裡來的,為什麼不被擴展事件拾取?
單行插入獲取
X
新行上的(獨占)鎖。
SELECT
嘗試獲取範圍共享的密鑰共享 ( )RangeS-S
鎖。此請求由
lock_acquired
擴展事件報告為 mode =RS_S
。Profiler 事件類將其報告
Lock:Acquired
為模式 13 (LCK_M_RS_S
)。請求的模式與 in中現有的獨占鎖模式相結合。沒有範圍共享,鍵獨占()的組合模式,因此計算的結果是范圍獨占,鍵獨占(),恰好是模式15。
Lock::CalculateGrantMode``sqlmin.dll``RangeS-X``RangeX-X
上面的授權模式計算是在擴展事件生成之前執行的
lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>
。儘管如此,Profiler 和 Extended Events 都會記錄請求RangeS-S
的模式,而不是生成的鎖定模式RangeX-X
。這與有限的文件相反,它說:模式 | 整數| 獲取鎖後的結果模式。
擴展事件的模式欄根本沒有文件,元數據中的描述是空白的。也許微軟自己甚至不確定這種行為。
我經常認為如果鎖定事件同時報告請求模式和結果模式會更有用,但這不是我們所擁有的。目前的安排使得幾乎不可能跟踪和匹配鎖的獲取和釋放。
以這種方式報告鎖可能有充分的理由。如果它不能滿足你的需求,你可以向 Microsoft 開一個支持案例,或者創建一個 Azure 回饋項。
LAST_MODE
神秘
LAST_MODE
是埃里克·達林(Erik Darling)以前說過的。它是map_key
公開的鎖定模式列表中的最大值sys.dm_xe_map_values
:SELECT DXMV.map_key, DXMV.map_value FROM sys.dm_xe_map_values AS DXMV WHERE DXMV.[name] = N'lock_mode' ORDER BY DXMV.map_key;
╔═════════╦═══════════╗ ║ map_key ║ map_value ║ ╠═════════╬═══════════╣ ║ 0 ║ NL ║ ║ 1 ║ SCH_S ║ ║ 2 ║ SCH_M ║ ║ 3 ║ S ║ ║ 4 ║ U ║ ║ 5 ║ X ║ ║ 6 ║ IS ║ ║ 7 ║ IU ║ ║ 8 ║ IX ║ ║ 9 ║ SIU ║ ║ 10 ║ SIX ║ ║ 11 ║ UIX ║ ║ 12 ║ BU ║ ║ 13 ║ RS_S ║ ║ 14 ║ RS_U ║ ║ 15 ║ RI_NL ║ ║ 16 ║ RI_S ║ ║ 17 ║ RI_U ║ ║ 18 ║ RI_X ║ ║ 19 ║ RX_S ║ ║ 20 ║ RX_U ║ ║ 21 ║ LAST_MODE ║ ╚═════════╩═══════════╝
通過 DMV 訪問的記憶體結構(使用
sqlmin!CMapValuesTable
)儲存在地址 開始sqlmin!XeSqlPkg::g_lock_mode
。結構中的每個 16 字節條目都包含和指向流 TVFmap_key
返回的字元串的指針。map_value
字元串完全按照上表所示儲存(儘管不是按該順序)。
map_value
條目 21 具有“LAST_MODE”而不是預期的“RX_X”似乎是一個錯誤。Erik Darling在 Azure 回饋上報告了該問題。