Verfolgen von Blockierungen, die weniger als eine Sekunde dauern - SQL Server

14

Ich versuche, ein Blockierungsproblem zu beheben, das weniger als eine Sekunde dauert. Die OLTP-Anwendung ist sehr sensibel und muss für einige Transaktionen eine Antwortzeit von weniger als 200 ms gemäß dem vereinbarten SLA haben. Wir hatten einige Probleme mit der Eskalation von Sperren mit der neuen Codeversion, die wir durch die Reduzierung der Stapelgröße in den Updates beheben konnten. Selbst mit der geringen Stapelgröße vermuten wir, dass der neue SP dieselben Zeilen blockiert, die von den OLTP-Transaktionen aktualisiert werden.

Ich muss die Sitzung finden, die blockiert wird, und die Ressource, auf die gewartet wird. Nach meinem Verständnis kann die "Schwelle für blockierten Prozess" für mindestens 1 Sekunde festgelegt werden, sodass die Blockierung nicht erfasst wird.

Ich experimentiere mit den Ereignissen wait_info und wait_completed x.

Gibt es eine andere Möglichkeit, dies zu verfolgen? Vielen Dank

jesijesi
quelle
Dieselbe
TheGameiswar

Antworten:

10

Da Sie sich speziell für das Sperren und nicht für das allgemeine Warten interessieren, ist das locks_lock_waitserweiterte Ereignis besser geeignet.

Mit eingeschaltetem Filter increment >= 200

CREATE EVENT SESSION [locks_lock_waits] ON SERVER 
ADD EVENT sqlserver.locks_lock_waits(
        ACTION(sqlserver.sql_text)
            WHERE  ( [sqlserver].[is_system] = 0
                     AND [increment] >= 200
                     AND [counter] <= 1000 ) 
    )
ADD TARGET package0.ring_buffer;

GO

ALTER EVENT SESSION [locks_lock_waits]  
ON SERVER  STATE = start;  

Das oben Gesagte sammelt die Anweisungen, die auf Sperren für den Schwellenwert warten, gibt aber nicht die spezifische Sperrressource an.

Ich habe dieses Ereignis noch nie verwendet und weiß nicht, wie viel Overhead diese Sitzung auf Ihrem Produktionsserver verursachen würde.

Ich habe dieses Video zum Thema gefunden. Es wird dringend empfohlen, nach zu filtern counter, um die Anzahl der erfassten Ereignisse zu verringern.

Es wird auch ein altes, nicht dokumentiertes Legacy-Kommando erwähnt

dbcc lock(StallReportThreshold, 200) -- 200 is threshold in ms

Wobei (wenn das Ablaufverfolgungsflag 3605 aktiviert ist) begrenzte Informationen wie die folgenden in das SQL Server-Fehlerprotokoll ausgegeben werden.

Der Prozess 53 hat 6844 ms auf die S-Sperre für RID gewartet: 2: 1: 120: 2 Ergebnis: OKWAIT

Ich erwähne dies nur beiläufig, da ausgedehnte Veranstaltungen sowieso eindeutig vorzuziehen sind, da sie dokumentiert und viel leistungsfähiger sind.

Martin Smith
quelle
Ich habe locks_lock_waits getestet und wie Sie sagten, sind darin keine Ressourceninformationen enthalten. Aber ich wusste nicht, dass das Inkrement Zeit war. Gute Info dbcc lock, sieht gut aus. Wissen Sie, wie lange diese Informationen verfügbar sind, bevor sie in das Fehlerprotokoll geschrieben werden können?
Jesijesi
Entschuldigung, ich habe mich nicht klar ausgedrückt. Ich habe gefragt, wie lange es dauert, bis wir den Befehl dbcc lock ausführen. ZB passiert das Sperren und wenn ich nach einer Stunde dbcc lock starte, bekommen wir dann immer noch die Information?
Jesijesi
@jesijesi - Ich hatte bis heute noch nie davon gehört. Ich habe keine weiteren Informationen dazu. Ich kenne nicht einmal die Parameter, die zum Deaktivieren übergeben werden müssen. Sie werden jedoch dbcc lock(StallReportThreshold, 200) zuerst ausgeführt und geben die Informationen aus, sobald der Schwellenwert überschritten wird, solange das Ablaufverfolgungsflag 3605 aktiviert ist. SQL Server sammelt diese Informationen nicht, nur für den Fall, dass Sie sie später ausführen.
Martin Smith
2
Vielen Dank. Hinzufügen eines Links, der eine nützliche Funktion zum Konvertieren der resource_0,1,2-Werte in xevents enthält. sqlnotes.info/2011/10/24/…
jesijesi
5

Wenn Sie sich für das Sperren interessieren, stehen Ihnen mehrere erweiterte Ereignisse zur Verfügung:

lock_acquired
lock_released
lock_escalation

Die ersten beiden Ereignisse haben eine durationSpalte in (Mikrosekunden), nach der Sie nach Ihren Schwellenwerten filtern können. Sie haben auch eine resource_descriptionAktion, die Ihnen einige Details zu den beteiligten Ressourcen gibt.

Das lock_escalationEreignis verfügt auch über eine statementAktion, die Sie hinzufügen können, um die T-SQL-Anweisung zu erfassen, die die Sperreneskalation ausgelöst hat. Es hat auch escalation_cause. Hier ist eine Beispielsitzung:

CREATE EVENT SESSION [locking] ON SERVER 
ADD EVENT sqlserver.lock_acquired( SET collect_resource_description = (1) ),
ADD EVENT sqlserver.lock_escalation( SET collect_statement = (1) ),
ADD EVENT sqlserver.lock_released( SET collect_resource_description = (1) )
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO

Ich vermute, dass es wahrscheinlich einen Grund gibt, warum Sie den Schwellenwert für blockierte Prozessberichte nicht auf weniger als eine Sekunde festlegen können: Das Sperren ist in einem RDBMS völlig normal - das Datenbankmodul muss Ressourcen sperren, um sie zu schützen. Obwohl es keine offizielle Definition gibt, wann das Sperren blockiert wird, erscheint mir das Sperren in Sekundenbruchteilen normal.

wBob
quelle
1
Das Sperren wird blockiert, sobald einer anderen Person der Zugriff auf die Ressource verweigert wird und sie aufgrund der Sperre warten muss.
Martin Smith
Vielen Dank, ich plane, lock_acquired mit dem Feld duration zu verwenden.
Jesijesi
Viel Glück. Da Sie mit SQL Server 2014 arbeiten, können Sie speicherinterne OLTP-Tabellen mit nativ kompilierten gespeicherten Prozessen verwenden, die eine latchfreie Hochleistungsoption bieten. Sie können sich auch die Snapshot-Isolierung ansehen.
wBob