シリアル化可能な分離の下で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)が取得されなかったにもかかわらず、リリースされたことがわかります。
拡張イベントでallロックを確認しました-フィルタリングなし。 RX-Xロックは取得されませんでした。
私はプロファイラーも試してみました:同じ結果です(もちろん、名前が正しくなります... "LAST_MODE"はありません)。
ロックのエスカレーションのためにXEを実行しました-ありません。
変換専用のXEはありませんが、少なくともUからXへのロック変換がlock_acquired
によってキャプチャされていることを確認できました
また、RI-Nは取得されますが、リリースされることはありません。私の現在の仮説は、RX-Xが here で説明されているように変換ロックであるというものです。バッチにキー範囲ロックが重複しており、変換の対象となるように見えますが、RX-Xロックは変換テーブルにありません。
このロックはどこから来ているのですか、なぜ拡張イベントによって取得されないのですか?
単一行の挿入により、新しい行のX
(排他的)ロックが取得されます。
SELECT
は、範囲共有、キー共有(RangeS-S
)ロックの取得を試みます。
このリクエストは、lock_acquired
拡張イベントによって、mode = RS_S
として報告されます。
プロファイラーイベントクラスLock:Acquired
によって、モード13(LCK_M_RS_S
)として報告されます。
要求されたモードは、Lock::CalculateGrantMode
のsqlmin.dll
の既存のexclusiveロックモードと組み合わされます。範囲共有、キー排他(RangeS-X
)の組み合わせモードがないため、計算の結果は範囲排他、キー排他(RangeX-X
)となり、モード15になります。
上記の許可モードの計算は、拡張イベントがlck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>
によって生成される直前に実行されます。それにもかかわらず、プロファイラーと拡張イベントの両方がrequestedRangeS-S
モードをログに記録し、結果のロックモードRangeX-X
はログに記録しません。これは、制限された documentation に対抗します。
モード| int| ロックが取得された後の結果のモード。
拡張イベントのmode列にはドキュメントがまったくなく、メタデータの説明は空白です。おそらく、マイクロソフト自身もその振る舞いを確信していませんでした。
ロックイベントがrequestedとresultingモードの両方を報告した方が便利だとよく思っていましたが、これは持ってる。現在の配置では、ロックの取得と解放を追跡して一致させることはほとんど不可能です。
mightこの方法でロックを報告するのには十分な理由があります。ニーズに合わない場合は、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 ║
╚═════════╩═══════════╝
(sqlmin!CMapValuesTable
を使用して)DMVを介してアクセスされるメモリ構造は、アドレスsqlmin!XeSqlPkg::g_lock_mode
から格納されます。構造内の各16バイトエントリには、map_key
と、ストリーミングTVFによってmap_value
として返される文字列へのポインターが含まれます。
文字列は、上記の表に示されているとおりに格納されます(ただし、この順序ではありません)。エントリ21のmap_value
が期待される「RX_X」ではなく「LAST_MODE」であると、エラーのようです。 Erik Darlingは Azureフィードバックで問題を報告しました を持っています。