Dies ist der zweite Artikel in der Reihe, die dem SQL Server-Transaktionsprotokoll und seinen Besonderheiten gewidmet ist. Hier werden wir die Details der Protokolldatensätze untersuchen.
Protokollaufzeichnungen
Protokolldatensätze sind der Kern der Protokollierungs- und Wiederherstellungsmechanismen. Ein Protokollsatz beschreibt eine einzelne Änderung in einer Datenbank. Somit hat jede Änderung an einer Datenbank einen oder mehrere Protokolldatensätze, die dabei helfen, diese bestimmte Änderung zu beschreiben. Obwohl Sie die Details der Protokolldatensätze nicht verstehen müssen, sind diese Details äußerst interessant, um zu verstehen, was mit Protokollierung und Wiederherstellung vor sich geht.
Der Protokolldatensatz hat eine eindeutige Protokollsequenznummer, die wir im ersten Artikel definiert haben. Die Protokollfolgenummer ermöglicht das Auffinden des Protokollsatzes im Transaktionsprotokoll. Außerdem hat jede Datendateiseite eine LSN in ihrem Seitenkopf, die den neuesten Protokolldatensatz identifiziert, dessen Änderung auf der Seite widergespiegelt wird. Dies ist entscheidend für die Wiederherstellung nach einem Absturz.
Protokolldatensätze für gleichzeitige Transaktionen werden im Transaktionsprotokoll entsprechend dem zeitlichen Auftreten vermischt. Protokolldatensätze werden in Protokollblöcken im Pufferpool gespeichert, bis sie auf die Festplatte geschrieben werden.
Es gibt keine nicht protokollierten Vorgänge in Benutzer- oder Systemdatenbanken. Es gibt jedoch eine Ausnahme:In tempdb werden Versionsspeicher- und Arbeitsdateivorgänge nicht protokolliert. Protokollaufzeichnungen werden niemals im Transaktionsprotokoll verschoben.
Was ist in einem Protokolldatensatz enthalten?
Informationen in einem Protokolldatensatz ermöglichen es, ihn zu wiederholen (Rollforward) oder rückgängig zu machen (Rollback). Diese Fähigkeit eines Protokollsatzes ist entscheidend, damit Transaktionen rückgängig gemacht werden können und Wiederherstellungsarbeiten durchgeführt werden können. Protokolldatensätze enthalten je nach Typ des Protokolldatensatzes viele Felder. Es gibt einige Felder, die allen Datensätzen gemeinsam sind, darunter:
- Der Protokolleintragstyp
- Transaktionsprotokollaufzeichnung beginnen
- Transaktionsprotokolldatensatz festschreiben
- Zuordnen einer Seite durch Ändern der Zuordnungsbitmap
- Zeile einfügen
- Löschen einer Zeile
- Ändern einer Zeile
- Der Kontext des Protokolleintrags , falls vorhanden.
- Die Transaktions-ID, zu der der Protokolldatensatz gehört wenn überhaupt. Die meisten Protokolldatensätze sind Teil von Transaktionen.
- Die Protokollaufzeichnungslänge . Protokolldatensätze haben normalerweise eine feste Größe, und abhängig von der Datenmenge, die sich im Protokolldatensatz befindet, gibt es auch einen variablen Anteil.
- Die LSN des vorherigen Protokolleintrags in derselben Transaktion . Wenn überhaupt. Die LSN ist im Wesentlichen ein Zeiger auf den vorherigen Transaktionsprotokolldatensatz, der von dieser bestimmten Transaktion generiert wurde. Diese Kette der vorherigen LSNs ermöglicht das Zurücksetzen dieser bestimmten Transaktion, da das Zurücksetzen in umgekehrter Reihenfolge erfolgt, beginnend mit dem neuesten Protokolldatensatz.
- Die Menge an reserviertem Protokollspeicherplatz falls der Protokolleintrag rückgängig gemacht werden muss.
Protokollplatzreservierung
Jeder Protokolldatensatz, der im Vorwärtsteil einer Transaktion generiert wird, muss freien Speicherplatz im Transaktionsprotokoll reservieren, damit der Protokolldatensatz zurückgesetzt werden kann, ohne dass das Transaktionsprotokoll wachsen muss.
Der Reservierungsmechanismus für den Protokollspeicherplatz ist sehr konservativ und reserviert immer genügend Speicherplatz und normalerweise mehr, nur für den Fall, dass eine unerwartete Situation eintritt. Beispielsweise reserviert eine Aktualisierung oder Löschung einer komprimierten Tabelle mehr Speicherplatz als eine ähnliche Aktualisierung oder Löschung einer nicht komprimierten Tabelle. Dies geschieht, weil das Rollback der Aktualisierung für die komprimierte Tabelle möglicherweise damit zurechtkommen muss, dass sich die aktualisierte Zeile nicht mehr auf einer komprimierten Seite befindet, und daher statt komprimierter Daten Spalten mit voller Breite in den Protokolldatensatz schreiben müsste.
Typen von Protokolldatensätzen
Es gibt viele Arten von Protokolleinträgen, darunter:
- LOP_FORMAT_PAGE Bei der Protokollformatseitenoperation wurde eine Seite formatiert, was bedeutet, dass ihre Kopfzeile erstellt wurde. Der Protokolldatensatz protokolliert mindestens den Seitenkopf und möglicherweise weitere Inhalte der Seite, wenn die Seite als Teil einer Operation wie einer Indexerstellung oder -neuerstellung erstellt und ausgefüllt wurde)
- LOP_MODIFY_ROW Dieser Vorgang ändert einen kleinen Teil bestehender Daten.
- LOP_SET_BITS Dieser Protokolleintrag gilt für Zuordnungsbitmaps.
- LOP_INSERT_ROWS und LOP_DELETE_ROWS
- LOP_SET_FREE_SPACE Gilt für PFS – die Zuweisung der Bitmap, die den Zuweisungsstatus von Seiten verfolgt.
Alle Protokolldatensätze, die eine Änderung an einer Datenseite oder einer Indexseite in einem tabellarischen Index vornehmen, umfassen :
- Die Zuordnungseinheits-ID
- Die Seiten-ID und die Slot-ID des Datensatzes auf der Seite, die im Wesentlichen die nullbasierte Datensatz-ID des Daten- oder Indexdatensatzes auf der Seite ist.
- Das After-Image oder das Before-Image und After-Image der geänderten Daten. In einem einzelnen Protokolldatensatz können mehrere Sätze davon enthalten sein. Nachbilder ermöglichen die Wiederholung. Before-Images ermöglichen das Rückgängigmachen.
Protokollierung sperren
Einige Protokolldatensätze enthalten eine Bitmap davon, welche Sperren gehalten wurden, als die beschriebene Änderung stattfand. Die Bitmap enthält:
- Anzahl der Sperren.
- Welcher Typ und Modus der Sperre – zum Beispiel eine Seitensperre im X-Modus.
- Wofür die Sperre aktiviert ist
Während der Wiederherstellung nach einem Absturz und der Datenbankspiegelung/Verfügbarkeitsgruppen-Failover werden diese Sperren für alle Protokolldatensätze erworben, die rückgängig gemacht werden. Dies ermöglicht die schnelle Wiederherstellungsfunktion in der Enterprise Edition ab SQL Server 2005.
Aufzeichnungen in Transaktionen protokollieren
Alle Transaktionen generieren mindestens drei Protokollsätze, immer in der folgenden Reihenfolge:
- LOP_BEGIN_XACT – Enthält Informationen wie SPID, Transaktionsname und Startzeit. Alle von SQL Server gestarteten Transaktionen haben Namen zur Beschreibung der Operation (z. B. AllocFirstPage, DROPOBJ)
- Andere Datensätze für die Transaktion.
- LOP_COMMIT_XACT – wenn die Transaktion festgeschrieben wird.
- LOP_ABORT_XACT – wenn die Transaktion zurückgesetzt wird.
Beide enthalten die Endzeit der Transaktion.
Protokolldatensätze in einer Transaktion werden von LSN rückwärts miteinander verknüpft. Das bedeutet, dass der nächste Protokollsatz, der für eine Transaktion generiert wird, die LSN des vorherigen Protokollsatzes hat, der für diese bestimmte Transaktion generiert wurde. Dadurch kann die Transaktion korrekt rückgängig gemacht werden. Einige Protokolldatensätze sind überhaupt nicht transaktional, darunter:
- Änderungen des PFS-freien Speicherplatzes (kein Abgleich mit anderen Transaktionen möglich)
- Differentiale Bitmap-Änderungen (nur Änderung in eine Richtung)
Untersuchen von Protokolldatensätzen
Es gibt zwei Möglichkeiten, Protokolldatensätze zu untersuchen. Sie können die Funktion DBCC LOGINFO verwenden, es wird jedoch empfohlen, die Tabellenwertfunktion fn_dblog zu verwenden. Es hat eine extrem einfache Syntax:
SELECT * FROM fn_dblog (startLSN, endLSN); GO
Es ist eine extrem leistungsfähige Funktion, weil es:
- gibt eine tabellarische Ergebnismenge zurück, die einfach verwaltet werden kann.
- ermöglicht die Verwendung komplexer Prädikate.
- scannt das gesamte Transaktionsprotokoll im aktiven Teil des Protokolls, vom Beginn der ältesten nicht festgeschriebenen Transaktion bis zum neuesten Protokolldatensatz. Dies kann mit dem Trace-Flag 2537 überschrieben werden
Die Felder startLSN und endLSN werden normalerweise als NULL übergeben
Hier ist die Demo:
USE DBTest2014 GO SET NOCOUNT ON; GO --Set the SIMPLE recovery mode with no auto-stats -- to avoid unwanted log records ALTER DATABASE DBTest2014 SET RECOVERY SIMPLE; ALTER DATABASE DBTest2014 SET AUTO_CREATE_STATISTICS OFF; CREATE TABLE [TEST_TABLE] ([C1] INT, [C2] INT, [C3] INT); INSERT INTO [TEST_TABLE] VALUES (1,1,1); GO --Clear out the log CHECKPOINT; GO -- Implicit transaction INSERT INTO [TEST_TABLE] VALUES (2,2,2); GO SELECT * FROM fn_dblog(null, null); GO
Hier ist die verkürzte Ergebnismenge. Tatsächlich gibt fn_dblog eine Vielzahl verschiedener Datensätze zurück, wie z
Ändern von Zeileninhalten
Protokolländerungen werden auf zwei Arten protokolliert:als LOP_MODIFY_ROW oder LOP_MODIFY_COLUMNS Aufzeichnung. Unabhängig davon, welche Methode verwendet wird, werden die tatsächlich geänderten Bytes protokolliert. Wenn Sie beispielsweise einen INT-Wert von 1 auf 24 ändern, wird nur ein Byte der Änderung protokolliert, da sich die anderen drei Null-Bytes nicht geändert haben. SQL Server verwendet eine LOP_MODIFY_ROW Protokolldatensatz, wenn ein einzelner Teil der Zeile aktualisiert wird. Ein Abschnitt ist wie folgt definiert:Jede Spalte mit variabler Länge in der Zeile ist ein „Abschnitt“ und der gesamte Bereich mit fester Breite der Zeile ist ein „Abschnitt“, selbst wenn mehrere Spalten aktualisiert werden, aber nur, wenn die Bytes aktualisiert werden aktualisiert sind 16 Byte oder weniger auseinander in der Zeile.
LOP_MODIFY_ROW enthält:
- Vorher-Bild
- Nachher-Bild
- Indexschlüsselspalten, falls zutreffend
- Bitmap sperren
LOP_MODIFY_COLUMNS enthält:
- Array vor und nach Offsets
- Längen-Array
- Indexschlüsselspalten, falls zutreffend
- Bitmap sperren
- Vorher-Nachher-Bildpaare
Vergütungsprotokollaufzeichnungen
Dies ist eine spezielle Art von Protokolleinträgen, die verwendet werden, um ein Transaktions-Rollback zu unterstützen. Wenn eine Transaktion rückgängig gemacht wird, muss die von jedem Protokollsatz in der Transaktion beschriebene Änderung in der Datenbank rückgängig gemacht werden. Das Rollback beginnt mit dem neuesten Protokolldatensatz für die Transaktion und folgt den vorherigen LSN-Links bis zum LOP_BEGIN_XACT-Protokolldatensatz. Für jeden Protokolleintrag:
- Führen Sie die „Anti-Operation“ durch, die die Auswirkungen des Protokolleintrags zunichte macht
- Generieren Sie einen Protokolldatensatz und markieren Sie ihn als COMPENSATION-Protokolldatensatz, da er den Protokolldatensatz im Vorwärtsteil der Transaktion kompensiert.
- Die vorherige LSN des COMPENSATION-Protokolldatensatzes verweist auf den Protokolldatensatz vor demjenigen, für den er kompensiert wird. Es bewirkt im Wesentlichen, dass der Protokolldatensatz nicht mehr Teil der Kette von Protokolldatensätzen für die Transaktion ist.
- Der reservierte Logspace für den Logeintrag wird freigegeben
COMPENSATION-Protokolleinträge können nicht rückgängig gemacht, sondern nur wiederhergestellt werden.
Rollback einer Transaktion
Hier ist eine grafische Darstellung dessen, was passiert, wenn eine Transaktion zurückgesetzt wird:
Sehen wir uns den folgenden Code an:
USE DBTest2014 GO SET NOCOUNT ON; GO ALTER DATABASE DBTest2014 SET RECOVERY SIMPLE; ALTER DATABASE DBTest2014 SET AUTO_CREATE_STATISTICS OFF; CREATE TABLE [TEST_TABLE] ([C1] INT, [C2] INT, [C3] INT); INSERT INTO [TEST_TABLE] VALUES (1,1,1); INSERT INTO [TEST_TABLE] VALUES (2,2,2); GO --Clear out the log CHECKPOINT; GO -- Explicit transaction to insert a new record BEGIN TRAN; INSERT INTO [TEST_TABLE] VALUES (3,3,3); GO SELECT * FROM fn_dblog(null, null); GO --Roll it back ROLLBACK TRAN; GO SELECT * FROM fn_dblog(null, null);
Hier sehen wir einen speziellen Protokolleintrag mit der Beschreibung „COMPENSATION“
Wenn wir uns die vorherige LSN ansehen, können wir diese LOP_INSERT_ROWS sehen das wir gemacht haben, führt zurück zu …0f40:0001 und dies ist die BEGIN-Transaktion, da der Vorwärtsteil der Transaktion mit dem vorherigen Protokolldatensatz zurückverknüpft ist. Die LOP_DELETE_ROW Der Kompensationsprotokoll-Datensatz verlinkt nicht zurück zu einem Datensatz, für den er kompensiert wird – er verlinkt zu ihm (zum BEGIN-Transaktionsprotokoll-Datensatz).
DELEDE hat also INSERT kompensiert und es aus der Liste der Protokolldatensätze entfernt. Der LOP_ABORT_XACT ist das Signal, dass die Transaktion mit dem Rollback beendet wird. Außerdem können Sie diesen LOP_ABORT_XACT sehen Links zurück zu LOP_BEGIN_XACT.
Wenn wir einen Ausgleichsprotokolleintrag erstellen, sinkt die Protokollplatzreservierung [-74]. Es gibt also tatsächlich etwas Platz zurück, der für den Vorwärtsteil der Transaktion reserviert war (LOP_INSERT_ROWS [178]). Wie Sie sehen können, ist das Reservierungssystem für Protokollspeicherplatz sehr konservativ – INSERT reserviert mehr Platz als DELETE zurückgibt.
Rollbacks und differentielle Sicherungen
Wenn für eine Datenbank ein vollständiges Backup erstellt wurde, aktualisiert eine Transaktion 100.000 Datensätze, aber die Transaktion wird rückgängig gemacht. Warum werden bei einem differentiellen Backup so viele Daten gesichert? Sicherlich bedeutet das Rollback der Transaktion, dass sich nichts geändert hat? Das hier fehlende Puzzleteil besteht darin, dass durch das Zurücksetzen einer Transaktion nicht alle Änderungen gelöscht werden, die durch die Transaktion vorgenommen wurden. Wie wir gesehen haben, muss der Rollback Kompensationsprotokollsätze generieren, da der Rollback andere Änderungen generieren muss, um den Vorwärtsteil der Transaktion zu kompensieren. Die Seitenköpfe aller betroffenen Seiten wurden mindestens zweimal geändert. Einmal, um die LSN der Seite für den Vorwärtsteil der Transaktion zu aktualisieren, und einmal, um die LSN der Seite für den Rollback-Teil der Transaktion zu aktualisieren. In beiden Fällen bewirkt die Aktualisierung, dass die Ausdehnung in der differenziellen Bitmap als geändert markiert wird. Es ist egal, was die Änderung war, nur dass sich etwas im Umfang geändert hat. Es gibt keine Möglichkeit, diese Extents von der differenziellen Sicherung auszuschließen.
Zusammenfassung
In diesem Artikel haben wir uns die Protokollaufzeichnungen angesehen. Protokolldatensätze sind der Kern der Protokollierungs- und Wiederherstellungsmechanismen. Jeder Änderung in einer Datenbank ist ein Protokolldatensatz zugeordnet. Jeder Protokolleintrag beschreibt eine kleine Änderung. Eine große Änderung hat mehrere Protokolldatensätze innerhalb einer einzelnen Transaktion. Es gibt viele verschiedene Arten von Protokolleinträgen und wir haben uns einige davon angesehen.
Das Transaktionsprotokoll ist ein im Wesentlichen riesiges Thema und ein paar Artikel reichen nicht aus, um alle Details zu enthüllen. Wenn Sie also detailliertere Informationen erhalten möchten, empfehle ich Ihnen, das folgende Buch zu lesen:SQL Server Transaction Log Management von Tony Davis und Gail Shaw und dieser Artikel:Transaktionsprotokollverwaltung.
Lesen Sie auch:
Tauchen Sie ein in das SQL Server-Transaktionsprotokoll – Teil 1
Tauchen Sie in das SQL Server-Transaktionsprotokoll ein – Teil 2