この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ます。適切なrelated_object_idでフィルタリングします... RX-Xはありません。

拡張イベント出力

ロールバックを実行した後、RX-X(LAST_MODE)がリリースされましたが、取得されていません。

LAST_MODE

私が試したこと

  • 拡張イベントですべてのロックを確認しました-フィルタリングはありません。RX-Xロックが取得されていません。

  • プロファイラーも試してみました:同じ結果です(もちろん名前が正しくなりますが、「LAST_MODE」はありません)。

  • ロックのエスカレーションのためにXEを実行しました-それはありません。

  • 変換専用のXEはありませんが、少なくともUからXロックへの変換がキャプチャされることを確認できました lock_acquired

また、注目されるのは、取得されるが決してリリースされないRI-Nです。私の現在の仮説は、RX-Xがここで説明されているように変換ロックであるということです。バッチには重複するキー範囲ロックがあり、それらは変換の対象となるように見えますが、RX-Xロックは変換テーブルにありません。

このロックはどこから来たのですか、そしてなぜ拡張イベントによって受け取られないのですか?

回答:


12

単一行の挿入はX、新しい行で(排他的)ロックを取得します。

SELECTレンジ共有鍵を取得しようとする試みは、(共有RangeS-S)ロック。

この要求は、lock_acquired拡張イベントによってmode =として報告されますRS_S

Profilerイベントクラスにより、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自身もその振る舞いを確信していなかったのでしょう。

ロックイベントが要求さモードと結果のモードの両方を報告する方が便利だとよく考えていましたが、それは私たちが持っているものではありません。現在の配置では、ロックの取得と解放を追跡して一致させることはほとんど不可能です。

この方法でロックを報告するのには、十分な理由があるかもしれません。ニーズに合わない場合は、Microsoftでサポートケースを開くか、Azureフィードバックアイテムを作成できます。


LAST_MODE

不思議なのLAST_MODEは、エリックダーリンが以前に述べたことです。以下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 ║
╚═════════╩═══════════╝

(を使用してsqlmin!CMapValuesTable)DMVを介してアクセスされるメモリ構造は、アドレスから保存されますsqlmin!XeSqlPkg::g_lock_mode。構造内の各16バイトエントリには、ストリーミングTVFによってmap_key返される文字列へのポインタとポインタが含まれますmap_value

文字列は、上記の表に示されているとおりに格納されます(ただし、この順序ではありません)。エントリ21 map_valueに予想される「RX_X」ではなく「LAST_MODE」が含まれていると、エラーのようです。Erik Darlingがこの問題をAzureフィードバックで報告しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.