Database
 sql >> Datenbank >  >> RDS >> Database

Der APPEND_ONLY_STORAGE_INSERT_POINT-Latch

In Fortsetzung meiner Artikelserie über Latches werde ich dieses Mal auf den APPEND_ONLY_STORAGE_INSERT_POINT-Latch eingehen und zeigen, wie er ein großer Engpass für hohe Update-Arbeitslasten sein kann, wenn beide Formen der Snapshot-Isolation verwendet werden.

Ich empfehle Ihnen dringend, den ersten Beitrag in der Serie vor diesem zu lesen, damit Sie über das gesamte allgemeine Hintergrundwissen über Verriegelungen verfügen.

Was ist der APPEND_ONLY_STORAGE_INSERT_POINT Latch?

Um diesen Latch zu erklären, muss ich ein wenig erklären, wie die Snapshot-Isolation funktioniert.

Wenn Sie eine der beiden Formen der Versionsverwaltung aktivieren, verwendet SQL Server einen Mechanismus namens Versionsverwaltung um Versionen vor der Änderung beizubehalten eines Datensatzes im Versionsspeicher in tempdb. Dies geschieht wie folgt:

  • Ein Datensatz wird als kurz vor der Änderung identifiziert.
  • Der aktuelle Datensatz wird in den Versionsspeicher kopiert.
  • Der Datensatz wird geändert.
  • Wenn der Datensatz noch kein 14-Byte-Versionierungs-Tag hatte , wird eins am Ende des Datensatzes hinzugefügt. Das Tag enthält einen Zeitstempel (keine Echtzeit) und einen Zeiger auf die vorherige Version des Datensatzes im Versionsspeicher.
  • Wenn der Datensatz bereits ein Versionierungs-Tag hatte, wird er mit dem neuen Zeitstempel und Versionsspeicherzeiger aktualisiert.

Der Zeitstempel für die instanzweite Versionierung wird erhöht, wenn eine neue Anweisung oder ein neuer Stapel beginnt oder eine neue Version eines Datensatzes erstellt wird, und zwar in jeder Datenbank, in der eine der beiden Formen der Snapshot-Isolation aktiviert ist. Dieser Zeitstempel wird verwendet, um sicherzustellen, dass eine Abfrage die richtige Version eines Datensatzes verarbeitet.

Stellen Sie sich beispielsweise eine Datenbank vor, bei der das Lesen von festgeschriebenen Snapshots aktiviert ist, sodass jede Anweisung garantiert die Datensätze zu dem Zeitpunkt sieht, zu dem die Anweisung gestartet wurde. Der Zeitstempel der Versionierung wird auf den Zeitpunkt gesetzt, zu dem die Anweisung gestartet wurde, sodass jeder Datensatz, auf den sie stößt, der einen höheren Zeitstempel hat, die „falsche“ Version ist, und daher muss die „richtige“ Version mit einem Zeitstempel vor dem Zeitstempel der Anweisung aus der abgerufen werden Version speichern. Die Mechanismen dieses Prozesses sind für die Zwecke dieses Beitrags nicht relevant.

Wie also werden die Versionen physisch im Versionsspeicher gespeichert? Der gesamte Datensatz vor der Änderung, einschließlich Spalten außerhalb der Zeile, wird in den Versionsspeicher kopiert, aufgeteilt in 8.000-Byte-Blöcke, die sich bei Bedarf über zwei Seiten erstrecken können (z. B. 2.000 Byte am Ende einer Seite und 6.000 Byte am Ende einer Seite). Beginn des nächsten). Dieser Spezialspeicher besteht aus Zuordnungseinheiten nur zum Anhängen und wird nur für Versionsspeicheroperationen verwendet. Es heißt so, weil neue Daten immer nur unmittelbar nach dem Ende der zuletzt eingegebenen Version angehängt werden können. Von Zeit zu Zeit wird eine neue Zuordnungseinheit erstellt, wodurch die regelmäßige Bereinigung des Versionsspeichers sehr effizient ist, da eine nicht benötigte Zuordnungseinheit einfach gelöscht werden kann. Nochmals, die Mechanismen dafür würden den Rahmen dieses Beitrags sprengen.

Und jetzt kommen wir zur Definition des Latches:Jeder Thread, der einen Vorab-Änderungsdatensatz in den Versionsspeicher kopieren muss, muss wissen, wo sich der Einfügepunkt in der aktuellen Append-Only-Allokationseinheit befindet. Diese Informationen werden durch den APPEND_ONLY_STORAGE_INSERT_POINT-Latch geschützt.

Wie wird der Latch zum Flaschenhals?

Hier ist das Problem:Es gibt nur einen akzeptablen Modus, in dem der APPEND_ONLY_STORAGE_INSERT_POINT-Latch erfasst werden kann:EX-Modus (exklusiv). Und wie Sie aus dem Intro-Beitrag zur Serie wissen, kann im EX-Modus immer nur ein Thread die Latte halten.

Zusammenführen all dieser Informationen:Wenn für eine oder mehrere Datenbanken die Snapshot-Isolation aktiviert ist und eine ausreichend hohe gleichzeitige Arbeitslast von Aktualisierungen für diese Datenbanken vorhanden ist, werden viele Versionen von den verschiedenen Verbindungen generiert, und dieser Latch wird zu einem ein kleiner Engpass, wobei die Engpassgröße zunimmt, wenn die Update-Arbeitslast zunimmt, wenn Versionierung involviert ist.

Aufzeigen des Engpasses

Sie können den Engpass leicht selbst reproduzieren. Ich tat dies wie folgt:

  • Erstellt eine Tabelle mit einer Reihe ganzzahliger Spalten mit dem Namen cXXX, wobei XXX eine Zahl ist, und einem gruppierten Index für eine int-Identitätsspalte mit dem Namen DocID
  • 100.000 Datensätze eingefügt, mit zufälligen Werten für alle Spalten
  • Erstellt ein Skript mit einer Endlosschleife, um eine zufällige DocID im Bereich von 1 bis 10.000 auszuwählen, einen zufälligen Spaltennamen auszuwählen und den Spaltenwert um 1 zu erhöhen (wodurch eine Version erstellt wird)
  • Neun identische Skripte erstellt, aber jeweils aus einem anderen Cluster-Schlüsselbereich mit 10.000 Werten ausgewählt
  • Setzen Sie DELAYED_DURABILITY auf FORCED, um WRITELOG-Wartezeiten zu reduzieren (zugegebenermaßen würden Sie dies selten tun, aber es hilft, den Engpass für Demozwecke zu verschärfen)

Ich habe dann alle zehn Skripts gleichzeitig ausgeführt und den Zähler Zugriffsmethoden:Indexsuchen/s gemessen, um zu verfolgen, wie viele Aktualisierungen aufgetreten sind. Ich konnte Databases:Batch Requests/sec nicht verwenden, da jedes Skript nur einen Batch (die Endlosschleife) hatte, und ich wollte Transactions/sec nicht verwenden, da es interne Transaktionen sowie diejenige zählen könnte, die jedes Update umschließt.

Wenn die Snapshot-Isolation nicht aktiviert war, erhielt ich auf meinem Windows 10-Laptop mit SQL Server 2019 etwa 80.000 Updates pro Sekunde über die zehn Verbindungen. Als ich dann die Einstellung READ_COMMMITED_SNAPSHOT für die Datenbank auf ON stellte und den Test erneut ausführte, sank der Workload-Durchsatz auf etwa 60.000 Aktualisierungen pro Sekunde (ein Rückgang des Durchsatzes um 25 %). Den Wartestatistiken zufolge waren 85 % aller Wartezeiten LATCH_EX, und den Latch-Statistiken zufolge waren 100 % APPEND_ONLY_STORAGE_INSERT_POINT.

Denken Sie daran, dass ich das Szenario eingerichtet habe, um den Engpass in seiner schlimmsten Form zu zeigen. In einer realen Umgebung mit gemischter Workload liegt die allgemein akzeptierte Richtlinie für einen Durchsatzabfall bei Verwendung der Snapshot-Isolation bei 10–15 %.

Zusammenfassung

Ein weiterer potenzieller Bereich, der von diesem Engpass betroffen sein könnte, sind von Verfügbarkeitsgruppen lesbare Secondaries. Wenn eine Datenbankreplik als lesbar festgelegt ist, verwenden alle Abfragen automatisch die Snapshot-Isolation, und alle Wiedergaben von Protokolldatensätzen von der primären Datenbank generieren Versionen. Bei einer ausreichend hohen Aktualisierungsarbeitslast von der primären und vielen Datenbanken, die als lesbar eingestellt sind, und da parallele Wiederholungen die Norm für sekundäre Verfügbarkeitsgruppen sind, kann der APPEND_ONLY_STORAGE_INSERT_POINT-Latch auch für eine lesbare sekundäre Verfügbarkeitsgruppe zu einem Engpass werden, was zu der führen kann sekundär hinter dem primären zurückfallen. Ich habe das nicht getestet, aber es ist genau derselbe Mechanismus, den ich oben beschrieben habe, also scheint es wahrscheinlich. In diesem Fall ist es möglich, die parallele Wiederherstellung mithilfe des Ablaufverfolgungsflags 3459 zu deaktivieren, aber dies kann zu einem schlechteren Gesamtdurchsatz auf dem Sekundärserver führen.

Abgesehen vom Verfügbarkeitsgruppenszenario ist leider der Verzicht auf die Snapshot-Isolation die einzige Möglichkeit, diesen Engpass vollständig zu vermeiden. Dies ist keine praktikable Option, wenn Ihre Workload auf der durch die Snapshot-Isolation bereitgestellten Semantik beruht oder Sie sie benötigen, um Blockierungsprobleme zu verringern (da Snapshot-Isolation bedeutet, dass Leseabfragen keine Freigabesperren erwerben, die Änderungsabfragen blockieren).

Bearbeiten:Aus den Kommentaren unten können Sie den Latch-Engpass entfernen, indem Sie ADR in SQL Server 2019 verwenden, aber dann ist die Leistung aufgrund des ADR-Overheads viel schlechter. Das Szenario, in dem der Latch aufgrund der hohen Update-Arbeitslast zu einem Engpass wird, ist absolut kein gültiger Anwendungsfall für ADR.