For*_*est 13 sql-server locking sql-server-2017
我有一对查询,在可序列化隔离下,会导致 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')
Run Code Online (Sandbox Code Playgroud)
这是我的问题批次:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
INSERT dbo.LockTest
VALUES ('bleh')
SELECT *
FROM dbo.LockTest
WHERE ID = SCOPE_IDENTITY()
--ROLLBACK
Run Code Online (Sandbox Code Playgroud)
我检查了这个会话持有的锁,并看到了 RX-X:
SELECT resource_type, request_mode, request_status, resource_description
FROM sys.dm_tran_locks
WHERE request_session_id = 72 --change SPID!
Run Code Online (Sandbox Code Playgroud)
但我在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 锁不在转换表中。
这个锁是从哪里来的,为什么它没有被扩展事件捡到?
Pau*_*ite 12
单行插入获取X对新行的(独占)锁。
所述SELECT获取范围共享,密钥共享的尝试(RangeS-S)锁。
此请求由lock_acquired扩展事件报告为 mode = RS_S。
Profiler 事件类Lock:Acquired将其报告为模式 13 ( LCK_M_RS_S)。
请求的模式与in中现有的排他锁模式相结合。不存在范围共享、键独占 ( ) 的组合模式,因此计算的结果是范围独占、键独占 ( ),恰好是模式 15。Lock::CalculateGrantModesqlmin.dllRangeS-XRangeX-X
上面的授权模式计算是在扩展事件由 生成之前执行的lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>。然而,探查器和扩展事件都记录请求的 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;
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
通过 DMV 访问的内存结构(使用sqlmin!CMapValuesTable)从地址 开始存储sqlmin!XeSqlPkg::g_lock_mode。结构中的每个 16 字节条目都包含map_key和 一个指向map_value流 TVF返回的字符串的指针。
字符串的存储完全如上表所示(尽管不是按此顺序)。条目 21 具有map_value“LAST_MODE”而不是预期的“RX_X”似乎是一个错误。Erik Darling 已在 Azure 反馈上报告了该问题。
| 归档时间: |
|
| 查看次数: |
354 次 |
| 最近记录: |