Mengapa penguncian RX-X ini tidak muncul di Extended Events?

13

Masalah

Saya memiliki sepasang pertanyaan yang, di bawah isolasi serializable, menyebabkan kunci RX-X. Namun, ketika saya menggunakan Extended Events untuk menonton akuisisi kunci, akuisisi kunci RX-X tidak pernah muncul, itu hanya dirilis. Dari mana asalnya?

Repro

Ini meja saya:

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')

Inilah kumpulan masalah saya:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN

INSERT dbo.LockTest
VALUES ('bleh')

SELECT *
FROM dbo.LockTest
WHERE ID = SCOPE_IDENTITY()

--ROLLBACK

Saya memeriksa kunci yang dipegang oleh sesi ini, dan melihat 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

Tapi saya juga punya acara diperpanjang pada lock_acquireddan lock_released. Saya memfilternya pada associ_object_id yang sesuai ... tidak ada RX-X.

Output acara diperpanjang

Setelah menjalankan rollback, saya melihat RX-X (LAST_MODE) dirilis, meskipun tidak pernah diperoleh.

LAST_MODE

Apa yang saya coba

  • Saya melihat semua kunci di Extended Events - tanpa filter. Tidak ada kunci RX-X yang diperoleh.

  • Saya juga mencoba Profiler: hasil yang sama (kecuali tentu saja namanya tepat ... tidak ada "LAST_MODE").

  • Saya menjalankan XE untuk eskalasi kunci - tidak ada di sana.

  • Tidak ada XE khusus untuk konversi, tetapi saya dapat mengonfirmasi bahwa setidaknya konversi kunci U ke X ditangkap oleh lock_acquired

Yang juga perlu diperhatikan adalah RI-N yang didapat tetapi tidak pernah dirilis. Hipotesis saya saat ini adalah bahwa RX-X adalah kunci konversi, seperti dijelaskan di sini . Ada kunci rentang kunci yang tumpang tindih dalam kumpulan saya yang sepertinya harus memenuhi syarat untuk konversi, tetapi kunci RX-X tidak ada dalam tabel konversi.

Dari mana kunci ini berasal, dan mengapa tidak diambil oleh Extended Events?

Forrest
sumber

Jawaban:

12

Insert baris tunggal memperoleh Xkunci (eksklusif) pada baris baru.

The SELECTupaya untuk memperoleh berbagai-berbagi, kunci bersama ( RangeS-S) kunci.

Permintaan ini dilaporkan oleh lock_acquiredExtended Event sebagai mode = RS_S.

Ini dilaporkan oleh kelas peristiwa Profiler Lock:Acquiredsebagai mode 13 ( LCK_M_RS_S).

Mode yang diminta dikombinasikan dengan mode kunci eksklusif yang ada di Lock::CalculateGrantModedalam sqlmin.dll. Tidak ada mode gabungan rentang-bersama, kunci eksklusif ( RangeS-X) sehingga hasil perhitungan adalah rentang-eksklusif, kunci eksklusif ( RangeX-X), yang merupakan mode 15.

Perhitungan mode hibah di atas dilakukan sesaat sebelum acara yang diperluas dibuat oleh lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>. Namun demikian, baik Profiler dan Extended Events mencatat mode yang diminta RangeS-S , bukan mode kunci yang dihasilkan RangeX-X. Ini bertentangan dengan dokumentasi terbatas , yang mengatakan:

Mode | int | Mode yang dihasilkan setelah kunci diperoleh.

The modus kolom acara diperpanjang tidak memiliki dokumentasi sama sekali, dan deskripsi di meta data yang kosong. Mungkin Microsoft sendiri bahkan tidak yakin dengan perilakunya.

Saya sering berpikir akan lebih bermanfaat jika acara penguncian melaporkan mode yang diminta dan yang dihasilkan , tetapi bukan itu yang kami miliki. Pengaturan saat ini membuatnya sangat tidak mungkin untuk melacak dan mencocokkan akuisisi dan pelepasan kunci.

Ada mungkin menjadi alasan yang baik untuk melaporkan kunci cara ini. Jika tidak memenuhi kebutuhan Anda, Anda bisa membuka kasing dukungan dengan Microsoft, atau membuat item Umpan Balik Azure.


LAST_MODE

Misterius LAST_MODEadalah sesuatu yang dikatakan Erik Darling sebelumnya . Ini adalah nilai tertinggi map_keydalam daftar mode kunci yang diekspos oleh 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 ║
╚═════════╩═══════════╝

Struktur memori yang diakses melalui DMV (menggunakan sqlmin!CMapValuesTable) disimpan mulai dari alamat sqlmin!XeSqlPkg::g_lock_mode. Setiap entri 16 byte dalam struktur berisi map_keydan penunjuk ke string yang dikembalikan map_valueoleh TVF streaming.

String disimpan persis seperti yang ditunjukkan pada tabel di atas (meskipun tidak dalam urutan itu). Tampaknya ada kesalahan bahwa entri 21 memiliki map_value"LAST_MODE" alih-alih "RX_X" yang diharapkan. Erik Darling telah melaporkan masalah ini pada Azure Feedback .

Paul White 9
sumber