为什么此RX-X锁没有出现在扩展事件中?


13

问题

我有一对可串行隔离的查询,它们导致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!

dm_tran_locks

但我在lock_acquired和也有一个扩展活动lock_released。我在适当的associated_object_id上对其进行过滤...没有RX-X。

扩展事件输出

执行回滚后,即使从未获得过RX-X(LAST_MODE),我也看到它已发布。

LAST_MODE

我尝试过的

  • 我查看了扩展事件中的所有锁-没有过滤。未获得RX-X锁。

  • 我还尝试了Profiler:相同的结果(当然,它的名称正确...没有“ LAST_MODE”)。

  • 我运行XE进行锁升级-它不在那里。

  • 没有专门用于转换的XE,但我能够确认至少U到X锁定转换已被捕获 lock_acquired

还值得注意的是被收购但从未发布的RI-N。我现在的假设是,RX-X是一个转换锁,如所描述这里。我的批处理中有重叠的键范围锁,看起来它们应该可以进行转换,但是RX-X锁不在转换表中。

此锁来自何处,为什么扩展事件未将其锁定?

Answers:


12

单行插入获取X新行上的(独占)锁。

所述SELECT获取范围共享,密钥共享的尝试(RangeS-S)锁。

lock_acquired扩展事件将该请求报告为mode = RS_S

事件探查器事件类Lock:Acquired将其报告为模式13(LCK_M_RS_S)。

所请求的模式与已有的合成独占锁定模式Lock::CalculateGrantModesqlmin.dll。没有范围共享,键排他(RangeS-X)的组合模式,因此计算结果是范围互斥的键排他(RangeX-X),恰好是模式15。

上面的授予模式计算是在产生扩展事件之前执行的lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>。尽管如此,探查器和扩展事件都记录请求的 RangeS-S模式,而不记录结果的锁定模式RangeX-X。这与有限的文档相反:

模式| int | 获取锁定后的结果模式。

扩展事件的模式列完全没有文档,并且元数据中的描述为空白。也许微软自己甚至不确定这种行为。

我经常认为,如果锁定事件报告了请求的模式和结果模式,这将更有用,但这不是我们所拥有的。当前的安排几乎不可能跟踪和匹配锁的获取和释放。

可能是报告锁这样一个很好的理由。如果它不能满足您的需求,则可以向Microsoft打开支持案例,或创建一个Azure反馈项目。


LAST_MODE

神秘的LAST_MODE东西埃里克·达林已经之前说的。它是map_keysys.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)访问的存储结构从address开始存储sqlmin!XeSqlPkg::g_lock_mode。结构中的每个16字节条目都包含map_key和和指向map_value流式TVF 返回的字符串的指针。

字符串的存储方式完全与上表中所示(但不按该顺序)。条目21具有map_value“ LAST_MODE”而不是预期的“ RX_X” 似乎是一个错误。Erik Darling 在Azure反馈中报告了该问题

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.