Access
 sql >> Datenbank >  >> RDS >> Access

TRANSACTION_MUTEX und Multi-Session-Transaktionszugriff

Ich bin kürzlich auf einen hohen TRANSACTION_MUTEX gestoßen akkumulierte Wartezeit auf einem Client-System. Ich konnte mich an keinen Fall erinnern, in dem ich diese Art von Wartezeit ganz oben auf der Liste der „hohen Wartezeiten“ sah, und ich war neugierig, welche Faktoren diese Art von Wartezeit insgesamt beschleunigen könnten.

Die Books Online-Definition von TRANSACTION_MUTEX ist, dass es "während der Synchronisierung des Zugriffs auf eine Transaktion durch mehrere Stapel auftritt". Nicht viele Bereiche innerhalb der SQL Server-Engine verfügen über diese Art von Funktionalität, daher beschränkte sich meine Untersuchung auf die folgenden Technologien:

  • Das veraltete sp_getbindtoken und sp_bindsession Gespeicherte Systemprozeduren, die zur Verarbeitung gebundener Verbindungen verwendet werden
  • Verteilte Transaktionen
  • MARS (Mehrere aktive Ergebnissätze)

Mein Ziel war es, jede Technologie zu testen und zu sehen, ob sie den TRANSACTION_MUTEX beeinflusst Wartetyp.

Der erste Test, den ich durchgeführt habe, verwendete das veraltete sp_getbindtoken und sp_bindsession Gespeicherte Prozeduren. Das sp_getbindtoken gibt eine Transaktionskennung zurück, die dann von sp_bindsession verwendet werden kann um mehrere Sitzungen für dieselbe Transaktion zusammenzubinden.

Vor jedem Testszenario habe ich darauf geachtet, die Wartestatistiken meiner SQL Server-Testinstanz zu löschen:

DBCC SQLPERF('waitstats', CLEAR);
GO

Auf meiner SQL Server-Testinstanz wurde SQL Server 2012 SP1 Developer Edition (11.0.3000) ausgeführt. Ich habe die Credit-Beispieldatenbank verwendet, obwohl Sie jede andere Art von Beispieldatenbank wie AdventureWorks verwenden könnten, wenn Sie möchten, da das Schema und die Datenverteilung für das Thema dieses Artikels nicht direkt relevant sind und zum Fahren nicht erforderlich waren der TRANSACTION_MUTEX Wartezeit.

sp_getbindtoken / sp_bindsession

Im ersten Sitzungsfenster von SQL Server Management Studio habe ich den folgenden Code ausgeführt, um eine Transaktion zu starten und das Bindungstoken für die Eintragung durch die anderen geplanten Sitzungen auszugeben:

USE Credit;
GO
 
BEGIN TRANSACTION;
 
DECLARE @out_token varchar(255);
 
EXECUTE sp_getbindtoken @out_token OUTPUT;
 
SELECT @out_token AS out_token;
GO

Dies hat ein @out_token zurückgegeben von S/Z5_GOHLaGY<^i]S9LXZ-5---.fE--- . In zwei separaten SQL Server Management Studio-Abfragefenstern habe ich den folgenden Code ausgeführt, um den vorhandenen Sitzungen beizutreten (Zugriff auf die gemeinsame Transaktion):

USE Credit;
GO
 
EXEC sp_bindsession 'S/Z5_GOHLaGY<^i]S9LXZ-5---.fE---';

Und während das erste Sitzungsfenster noch geöffnet war, startete ich die folgende Schleife, um die Tabelle der Gebührentabelle mit einem Gebührendatum zu aktualisieren, das dem aktuellen Datum und der aktuellen Uhrzeit entspricht, und führte dann die gleiche Logik in den anderen beiden Fenstern aus (drei aktive Sitzungen in der Schleife):

WHILE 1 = 1 
BEGIN
    UPDATE  dbo.charge
    SET     charge_dt = SYSDATETIME();
END

Nach ein paar Sekunden habe ich jede ausgeführte Abfrage abgebrochen. Von den drei Sitzungen konnte nur eine tatsächlich Aktualisierungen durchführen – obwohl die anderen beiden Sitzungen aktiv mit derselben Transaktion verbunden waren. Und wenn ich mir den TRANSACTION_MUTEX ansehe Wait-Typ, ich kann sehen, dass es tatsächlich inkrementiert wurde:

SELECT  [wait_type],
        [waiting_tasks_count],
        [wait_time_ms],
        [max_wait_time_ms],
        [signal_wait_time_ms]
FROM sys.dm_os_wait_stats
WHERE wait_type = 'TRANSACTION_MUTEX';

Die Ergebnisse für diesen speziellen Test waren wie folgt:

wait_type            waiting_tasks_count   wait_time_ms   max_wait_time_ms   signal_wait_time_ms
TRANSACTION_MUTEX    2                     181732         93899              0

Ich sehe also, dass es zwei wartende Aufgaben gab (die beiden Sitzungen, die gleichzeitig versuchten, dieselbe Tabelle über die Schleife zu aktualisieren). Da ich SET NOCOUNT ON nicht ausgeführt hatte , konnte ich sehen, dass nur das erste ausgeführte UPDATE Ich habe diese ähnliche Technik mit ein paar verschiedenen Variationen ausprobiert (zum Beispiel – vier Gesamtsitzungen mit drei Wartezeiten) – und dem TRANSACTION_MUTEX Inkrementierung zeigte ein ähnliches Verhalten. Ich habe auch den TRANSACTION_MUTEX gesehen Akkumulation beim gleichzeitigen Aktualisieren einer anderen Tabelle für jede Sitzung – daher waren keine Änderungen am selben Objekt in einer Schleife erforderlich, um den TRANSACTION_MUTEX zu reproduzieren Akkumulation der Wartezeit.

Verteilte Transaktionen

Mein nächster Test beinhaltete zu sehen, ob TRANSACTION_MUTEX Wartezeit wurde für verteilte Transaktionen erhöht. Für diesen Test habe ich zwei SQL Server-Instanzen und einen Verbindungsserver verwendet, der zwischen den beiden verbunden ist. MS DTC wurde ausgeführt und ordnungsgemäß konfiguriert, und ich habe den folgenden Code ausgeführt, der ein lokales DELETE ausführte und ein entferntes DELETE über den Verbindungsserver und hat dann die Änderungen rückgängig gemacht:

USE Credit;
GO
 
SET XACT_ABORT ON;
 
-- Assumes MS DTC service is available, running, properly configured
BEGIN DISTRIBUTED TRANSACTION;
 
DELETE [dbo].[charge] WHERE charge_no = 1;
DELETE [JOSEPHSACK-PC\AUGUSTUS].[Credit].[dbo].[charge] WHERE charge_no = 1;
 
ROLLBACK TRANSACTION;

Der TRANSACTION_MUTEX zeigte keine Aktivität auf dem lokalen Server:

wait_type            waiting_tasks_count   wait_time_ms   max_wait_time_ms   signal_wait_time_ms
TRANSACTION_MUTEX    0                     0              0                  0

Die Anzahl der wartenden Aufgaben wurde jedoch auf dem Remote-Server erhöht:

wait_type            waiting_tasks_count   wait_time_ms   max_wait_time_ms   signal_wait_time_ms
TRANSACTION_MUTEX    1                     0              0                  0

Meine Erwartung, dies zu sehen, wurde also bestätigt – angesichts der Tatsache, dass wir eine verteilte Transaktion mit mehr als einer Sitzung haben, die in irgendeiner Weise mit derselben Transaktion verbunden ist.

MARS (Mehrere aktive Ergebnissätze)

Was ist mit der Verwendung von Multiple Active Results Sets (MARS)? Würden wir auch TRANSACTION_MUTEX erwarten ansammeln, wenn sie mit der MARS-Nutzung in Verbindung stehen?

Dazu habe ich den folgenden C#-Konsolenanwendungscode verwendet, der von Microsoft Visual Studio mit meiner SQL Server 2012-Instanz und der Credit-Datenbank getestet wurde. Die Logik dessen, was ich tatsächlich tue, ist nicht sehr nützlich (gibt eine Zeile aus jeder Tabelle zurück), aber die Datenleser befinden sich auf derselben Verbindung und dem Verbindungsattribut MultipleActiveResultSets auf true gesetzt ist, also war es ausreichend zu überprüfen, ob MARS tatsächlich TRANSACTION_MUTEX steuern könnte auch Akkumulation:

string ConnString = @"Server=.;Database=Credit;Trusted_Connection=True;MultipleActiveResultSets=true;";
SqlConnection MARSCon = new SqlConnection(ConnString);
 
MARSCon.Open();
 
SqlCommand MARSCmd1 = new SqlCommand("SELECT payment_no FROM dbo.payment;", MARSCon);
SqlCommand MARSCmd2 = new SqlCommand("SELECT charge_no FROM dbo.charge;", MARSCon);
 
SqlDataReader MARSReader1 = MARSCmd1.ExecuteReader();
SqlDataReader MARSReader2 = MARSCmd2.ExecuteReader();
 
MARSReader1.Read();
MARSReader2.Read();
 
Console.WriteLine("\t{0}", MARSReader1[0]);
Console.WriteLine("\t{0}", MARSReader2[0]);

Nachdem ich diesen Code ausgeführt hatte, sah ich die folgende Häufung für TRANSACTION_MUTEX :

wait_type            waiting_tasks_count   wait_time_ms   max_wait_time_ms   signal_wait_time_ms
TRANSACTION_MUTEX    8                     2              0                  0

Wie Sie also sehen können, verursachte die MARS-Aktivität (wie auch immer trivial implementiert) einen Anstieg in TRANSACTION_MUTEX warten Typ Akkumulation. Und das Connection-String-Attribut selbst treibt dies nicht an, sondern die eigentliche Implementierung. Beispielsweise habe ich die zweite Reader-Implementierung entfernt und nur einen einzigen Reader mit MultipleActiveResultSets=true beibehalten , und wie erwartet gab es kein TRANSACTION_MUTEX Akkumulation der Wartezeit.

Schlussfolgerung

Wenn Sie einen hohen TRANSACTION_MUTEX sehen Wartezeiten in Ihrer Umgebung, ich hoffe, dieser Beitrag gibt Ihnen einen Einblick in drei Wege, die Sie erkunden können - um festzustellen, woher diese Wartezeiten kommen und ob sie notwendig sind oder nicht.


No