SQL Server 2014 CTP1 führt Warteoptionen für Sperren mit niedriger Priorität zur Verwendung mit Online-Indexoperationen und Partitionswechseln ein.
Für diejenigen, die die Online-Indexverwaltung oder Indexpartitionierung und Partitionswechselvorgänge in SQL Server 2012 Enterprise Edition nutzen, haben Sie möglicherweise irgendwann die Blockierung Ihres DDL-Vorgangs erlebt, da für diese Vorgänge noch einige Sperranforderungen gelten.
Stellen Sie sich zur Veranschaulichung vor, dass ich die folgende Einzelpartitions-Online-Indexneuerstellung in SQL Server 2014 CTP1 ausführe:
ALTER INDEX [ClusteredIndex_on_ps_ShipDate] ON [dbo].[FactInternetSales] REBUILD PARTITION = (37) WITH (ONLINE= ON);
Und werfen wir einen Blick auf die Sperren, die während dieses Neuerstellungsvorgangs mithilfe von erweiterten Ereignissen und der folgenden Sitzungsdefinition erworben und freigegeben wurden (dies ist eine ziellose Sitzung, und ich habe die Ergebnisse über den Bereich „Live-Daten beobachten“ in SQL Server Management Studio beobachtet):
CREATE EVENT SESSION [Online_Index_Rebuild_Locks_Taken] ON SERVER ADD EVENT sqlserver.lock_acquired( WHERE ([object_id]=(309576141))), ADD EVENT sqlserver.lock_released( WHERE ([object_id]=(309576141))) 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
Der Wert 309576141 stellt die Objekt-ID der FactInternetSales-Tabelle dar.
Mein Online-Index-Neuaufbau einer einzelnen Partition dauerte 56 Sekunden und nach Abschluss sah ich die folgende Lock-Acquiring- und -Release-Aktivität:
Aktivität für die Online-Wiederherstellung einer einzelnen Partition sperren
Wie Sie der Ausgabe entnehmen können, handelt es sich bei der Neuerstellung zwar um einen Online-Vorgang, es werden jedoch während des Lebenszyklus des Vorgangs Sperren in verschiedenen Modi erworben. Idealerweise ist die Sperrdauer minimal (zum Beispiel – der Zeitstempel ist identisch für den ersten SCH_S
Sperre erworben und freigegeben). Aber selbst mit einer minimalen Menge an Sperren können Sie sicherlich auf Nebenläufigkeitsprobleme stoßen, abhängig von den Transaktionen, die für den Index ausgeführt werden, der neu erstellt oder in den gewechselt wird.
Ich habe am Anfang dieses Beitrags erwähnt, dass Microsoft Warteoptionen für Sperren mit niedriger Priorität für Onlinevorgänge und Partitionswechselvorgänge in SQL Server 2014 CTP1 eingeführt hat. Zum Thema Partitionsschalter stellen Sie sich vor, ich würde die folgende Operation ausführen:
ALTER TABLE [AdventureWorksDW2012].[dbo].[FactInternetSales] SWITCH PARTITION 37 TO [AdventureWorksDW2012].[dbo].[staging_FactInternetSales];
Um die für diese Operation erworbenen und freigegebenen Sperren anzuzeigen, habe ich meine zuvor definierte erweiterte Ereignissitzung so geändert, dass sie die anwendbaren Objekte (Quell- und Zieltabelle) enthält. Ich habe Folgendes gesehen:
Sperraktivität für einen Partitionswechselvorgang
Der Umschaltvorgang auf eine leere Partition erfolgte in weniger als einer Sekunde, aber wir sehen immer noch diesen SCH_S
und SCH_M
Sperren waren während des Vorgangslebenszyklus sowohl auf der Quelle als auch auf dem Ziel erforderlich (309576141 ist FactInternetSales und 398624463 ist staging_FactInternetSales).
Auch wenn die Dauer der Sperrung extrem kurz sein kann, wenn keine gleichzeitigen Transaktionen auf die betreffenden Objekte zugreifen, wissen wir, dass dies nicht immer möglich ist, und daher können unsere Online-Indexneuaufbau- und Partitionswechseloperationen tatsächlich blockiert werden. P>
Mit dieser Realität führt SQL Server 2014 also den WAIT_AT_LOW_PRIORITY
ein Argument, das mit MAX_DURATION
angepasst werden kann und ABORT_AFTER_WAIT
Optionen sowohl für den ALTER INDEX
und ALTER TABLE
Befehle, die wir sowohl für Online-Index- als auch für Partitionswechseloperationen verwenden können.
Was ermöglicht uns das? Lassen Sie uns zunächst über das Verhalten vor SQL Server 2014 sprechen. Stellen Sie sich als Beispiel vor, dass die folgende Transaktion offen und nicht festgeschrieben ist:
BEGIN TRANSACTION; DELETE [dbo].[staging_FactInternetSales];
Wenn ich versucht habe, einen ALTER TABLE SWITCH
auszuführen an die Tabelle staging_FactInternetSales als Ziel in einer separaten Sitzung, werde ich blockiert und die Anfrage wartet einfach. Speziell für dieses Beispiel würde ich mit einem LCK_M_SCH_M
warten Wartetyp. Sobald ich meine Transaktion zurücksetze oder festschreibe, kann der Vorgang fortgesetzt und abgeschlossen werden.
Wenn ich jetzt WAIT_AT_LOW_PRIORITY
von SQL Server 2014 verwende mit MAX_DURATION
und ABORT_AFTER_WAIT
, kann ich je nach meinen Anwendungsanforderungen einige verschiedene Optionen nutzen.
MAX_DURATION
ermöglicht es mir, die Anzahl der Minuten anzugeben, die die Online-Indexneuerstellung oder der Partitionswechselvorgang warten soll. Wenn die MAX_DURATION
Wert erreicht ist, können wir basierend auf der Einstellung von ABORT_AFTER_WAIT
festlegen, was als nächstes passiert , der ein Wert von NONE
sein kann , SELF
oder BLOCKERS
:
NONE
bedeutet, dass die Indexoperation die Operation weiterhin versucht.SELF
bedeutet, dass wenn dieMAX_DURATION
erreicht ist, wird der Vorgang (der Online-Neuaufbau des Index oder der Partitionswechsel) abgebrochen.- Wenn
BLOCKERS
verwendet wird, werden alle Transaktionen beendet, die den Online-Indexneuaufbau oder den Partitionswechsel blockieren (meiner Meinung nach keine Option, die leichtfertig verwendet werden sollte).BLOCKERS
erfordert auchALTER ANY CONNECTION
Berechtigung für die Anforderung, die den Online-Indexneuaufbau oder den Partitionswechselvorgang ausgibt.
Die folgenden Codebeispiele demonstrieren verschiedene Konfigurationsvarianten.
Standardverhalten vor 2014 (unbegrenzt warten)
- Die Ausführung des Folgenden führt zu dem Verhalten, das wir von vor SQL Server 2014 gewohnt sind – und es könnte immer noch das sein, was Sie für bestimmte Szenarien wünschen oder erwarten:
ALTER TABLE [AdventureWorksDW2012].[dbo].[FactInternetSales] SWITCH PARTITION 37 TO [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 0 MINUTES, ABORT_AFTER_WAIT = NONE));
Warten Sie 1 Minute und brechen Sie den DDL-Vorgang ab
- Das folgende Beispiel wartet 1 Minute, wenn es eine blockierende Transaktion gibt, und erhält eine „Zeitüberschreitung der Sperranforderung“ für den
SWITCH
Betrieb, wenn die maximale Dauer erreicht ist: ALTER TABLE [AdventureWorksDW2012].[dbo].[FactInternetSales] SWITCH PARTITION 37 TO [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 1 MINUTES, ABORT_AFTER_WAIT = SELF));
Warte 1 Minute und töte den/die Blocker
- Dieses Beispiel wartet 1 Minute, wenn es eine blockierende Transaktion gibt, und beendet dann die blockierenden Transaktionen (einschließlich Quelle oder Ziel), wodurch der
SWITCH
ermöglicht wird Vorgang abzuschließen. ALTER TABLE [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] SWITCH PARTITION 37 TO [AdventureWorksDW2012].[dbo].[FactInternetSales] WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 1 MINUTES, ABORT_AFTER_WAIT = BLOCKERS));
In meinem Beispiel eines DELETE
Innerhalb einer nicht festgeschriebenen Transaktion gab es keinen Fehler in meinem SQL Server Management Studio-Fenster, da ich keine aktiv ausgeführte Anweisung hatte, aber der Versuch einer anderen Anweisung innerhalb dieser Sitzung gab die folgende Fehlermeldung zurück (da meine Sitzung beendet wurde):
Beim Senden der Anfrage an den Server ist ein Fehler auf Transportebene aufgetreten. (Anbieter:Shared Memory Provider, Fehler:0 – Am anderen Ende der Pipe befindet sich kein Prozess.)
Töte den/die Blocker sofort (Quelle oder Ziel für SWITCH)
- Das Folgende ist ein Beispiel für das sofortige Beenden des Blockers – und in meinem Beispiel erfolgte der Wechsel in weniger als einer Sekunde und tatsächlich wurde die Sitzung, die der Blocker war, beendet:
ALTER TABLE [AdventureWorksDW2012].[dbo].[FactInternetSales] SWITCH PARTITION 37 TO [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 0 MINUTES, ABORT_AFTER_WAIT = BLOCKERS));
Einen letzten positiven Aspekt wollte ich hervorheben…
Das SQL Server-Fehlerprotokoll bietet eine standardmäßige Überwachung der Verwendung von Sperren mit niedriger Priorität, einschließlich Informationen über ABORT_AFTER_WAIT
Operation inline mit den Opferinformationen:
Log SQL Server (Aktuell – 10.09.2013 12:03:00)
Quelle spid51
Nachricht
Prozess ID 57 wurde durch eine ABORT_AFTER_WAIT =BLOCKERS DDL-Anweisung auf database_id =5, object_id =309576141 beendet.
Und Sie sehen auch separate Einträge für die ursprüngliche Operation selbst. Zum Beispiel:
Eine ALTER TABLE SWITCH-Anweisung wurde auf der Datenbank „AdventureWorksDW2012“, der Tabelle „staging_FactInternetSales“ mit dem Hostnamen „WIN-4T7S36VMSD9“, der Hostprozess-ID 1360 mit der Zieltabelle „AdventureWorksDW2012.dbo.FactInternetSales“ unter Verwendung der WAIT_AT_LOW_PRIORITY-Optionen mit MAX_DURATION =1 und ABORT_AFTER_WAIT =ausgeführt BLOCKER. Blockierende Benutzersitzungen werden nach der maximalen Wartezeit beendet.Diese Art der Protokollierung ist sehr nützlich für Fehlerbehebungs- und Prüfungszwecke, und ich freue mich, sie zu sehen.