it-swarm.com.de

Warum wird diese RX-X-Sperre in erweiterten Ereignissen nicht angezeigt?

Das Problem

Ich habe zwei Abfragen, die unter serialisierbarer Isolation eine RX-X-Sperre verursachen. Wenn ich jedoch Extended Events verwende, um die Sperrerfassung zu überwachen, wird die RX-X-Sperrerfassung nie angezeigt, sondern nur freigegeben. Woher kommt das?

Der Repro

Hier ist mein Tisch:

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

Hier ist mein Problemstapel:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN

INSERT dbo.LockTest
VALUES ('bleh')

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

--ROLLBACK

Ich überprüfe die von dieser Sitzung gehaltenen Sperren und sehe 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

Ich habe aber auch ein erweitertes Ereignis für lock_acquired Und lock_released. Ich filtere es nach der entsprechenden verknüpften Objekt-ID ... es gibt kein RX-X.

(Extended Event output

Nach dem Ausführen des Rollbacks wird RX-X (LAST_MODE) freigegeben, obwohl es nie erworben wurde.

(LAST_MODE

Was ich versucht habe

  • Ich habe mir alle Sperren in Extended Events angesehen - keine Filterung. Es wurden keine RX-X-Sperren erworben.

  • Ich habe auch Profiler ausprobiert: gleiche Ergebnisse (außer natürlich, dass der Name richtig ist ... nein "LAST_MODE").

  • Ich habe den XE für Sperreneskalationen ausgeführt - er ist nicht vorhanden.

  • Es gibt kein XE speziell für Konvertierungen, aber ich konnte bestätigen, dass mindestens die Konvertierung der U-zu-X-Sperre von lock_acquired Erfasst wird.

Bemerkenswert ist auch der RI-N, der erworben, aber nie veröffentlicht wird. Meine aktuelle Hypothese ist, dass der RX-X eine Konvertierungssperre ist, wie beschrieben hier . In meinem Stapel befinden sich überlappende Schlüsselbereichssperren, die für die Konvertierung geeignet sein sollten, aber die RX-X-Sperre befindet sich nicht in der Konvertierungstabelle.

Woher kommt dieses Schloss und warum wird es nicht von Extended Events aufgenommen?

13
Forrest

Die Einfügung einer einzelnen Zeile erhält eine X (exklusive) Sperre für die neue Zeile.

Das SELECT versucht, eine Sperre mit gemeinsamem Schlüssel und gemeinsamem Schlüssel (RangeS-S) zu erhalten.

Diese Anforderung wird vom erweiterten Ereignis lock_acquired als mode = RS_S gemeldet.

Es wird von der Profiler-Ereignisklasse Lock:Acquired als Modus 13 (LCK_M_RS_S) gemeldet.

Der angeforderte Modus wird mit dem vorhandenen Sperrmodus exklusiv in Lock::CalculateGrantMode in sqlmin.dll kombiniert. Es gibt keinen kombinierten Modus für bereichsgeteilte, exklusive Schlüssel (RangeS-X), daher ist das Ergebnis der Berechnung bereichsexklusive, schlüsselexklusive (RangeX-X), was zufällig Modus 15 ist .

Die obige Berechnung des Grant-Modus wird unmittelbar vor der Generierung des erweiterten Ereignisses durch lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired> durchgeführt. Trotzdem protokollieren sowohl Profiler als auch Extended Events den Modus angefordertRangeS-S, nicht den resultierenden Sperrmodus RangeX-X. Dies steht im Widerspruch zu der begrenzten Dokumentation , die besagt:

Modus | int | Resultierender Modus nach dem Erwerb der Sperre.

Die Spalte mode des erweiterten Ereignisses enthält überhaupt keine Dokumentation, und die Beschreibung in den Metadaten ist leer. Vielleicht war sich Microsoft selbst des Verhaltens nicht einmal sicher.

Ich habe oft gedacht, es wäre nützlicher, wenn Sperrereignisse sowohl die Modi angefordert als auch resultierend melden würden, aber das ist nicht das, was wir haben. Die derzeitige Anordnung macht es so gut wie unmöglich, die Erfassung und Freigabe von Sperren zu verfolgen und abzugleichen.

Es gibt könnte einen guten Grund, Sperren auf diese Weise zu melden. Wenn es Ihren Anforderungen nicht entspricht, können Sie einen Support-Fall bei Microsoft öffnen oder ein Azure-Feedback-Element erstellen.


LAST_MODE

Das mysteriöse LAST_MODE ist etwas, das Erik Darling hat zuvor bemerkt . Dies ist der höchste map_key -Wert in der Liste der Sperrmodi, die von sys.dm_xe_map_values angezeigt werden:

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 ║
╚═════════╩═══════════╝

Die Speicherstruktur, auf die über die DMV zugegriffen wird (unter Verwendung von sqlmin!CMapValuesTable), wird ab der Adresse sqlmin!XeSqlPkg::g_lock_mode gespeichert. Jeder 16-Byte-Eintrag in der Struktur enthält den map_key und einen Zeiger auf die Zeichenfolge, die von der Streaming-TVF als map_value zurückgegeben wird.

Die Zeichenfolgen werden genau wie in der obigen Tabelle gezeigt gespeichert (jedoch nicht in dieser Reihenfolge). Es scheint ein Fehler zu sein, dass Eintrag 21 ein map_value von "LAST_MODE" anstelle des erwarteten "RX_X" hat. Erik Darling hat hat das Problem bei Azure Feedback gemeldet .

12
Paul White 9