Detaillierte Erläuterung des Persistenzimplementierungsprinzips von Transaktionen in MySQL

Detaillierte Erläuterung des Persistenzimplementierungsprinzips von Transaktionen in MySQL

Vorwort

Wenn es um Datenbanktransaktionen geht, fallen jedem schnell viele transaktionsbezogene Kenntnisse ein, wie etwa die ACID-Eigenschaften von Transaktionen, Isolationsebenen, gelöste Probleme (Dirty Reads, nicht wiederholbare Reads, Phantom Reads) usw., aber nur wenige Leute verstehen vielleicht wirklich, wie diese Transaktionseigenschaften implementiert werden und warum es vier Isolationsebenen gibt.

Im vorherigen Artikel haben wir das Implementierungsprinzip der Transaktionsisolation in MySQL kennengelernt. Lassen Sie uns heute weiter über das Implementierungsprinzip der MySQL-Persistenz sprechen.

Natürlich ist MySQL umfangreich und tiefgründig, und Auslassungen im Artikel sind unvermeidlich. Kritik und Korrekturen sind willkommen.

veranschaulichen

Die Transaktionsimplementierungslogik von MySQL befindet sich auf der Engine-Ebene und nicht alle Engines unterstützen Transaktionen. Die folgenden Anweisungen basieren auf der InnoDB-Engine.

InnoDB-Prinzip beim Lesen und Schreiben von Daten

Bevor wir fortfahren, müssen wir verstehen, wie InnoDB Daten liest und schreibt. Wir wissen, dass Datenbankdaten auf Festplatten gespeichert werden, und wir wissen auch, dass die Kosten für Festplatten-E/A sehr hoch sind. Wenn bei jedem Lesen oder Schreiben von Daten auf die Festplatte zugegriffen werden muss, ist die Effizienz der Datenbank sehr gering. Um dieses Problem zu lösen, stellt InnoDB einen Buffer Pool als Puffer für den Zugriff auf Datenbankdaten bereit.

Der Pufferpool befindet sich im Speicher und enthält eine Zuordnung einiger Datenseiten auf der Festplatte. Wenn Daten gelesen werden müssen, versucht InnoDB zunächst, sie aus dem Pufferpool zu lesen. Wenn die Daten nicht gelesen werden können, liest es sie von der Festplatte und legt sie im Pufferpool ab. Beim Schreiben von Daten schreibt es zunächst auf die Pufferpoolseite, markiert diese Seite als schmutzig und legt sie auf eine spezielle Flush-Liste. Diese geänderten Datenseiten werden zu einem späteren Zeitpunkt auf die Festplatte geleert (dieser Vorgang wird als Dirty Flushing bezeichnet und liegt in der Verantwortung anderer Hintergrundthreads). Wie in der folgenden Abbildung dargestellt:

Der Vorteil dieses Designs besteht darin, dass es eine große Menge an Festplatten-E/A in Lese- und Schreibvorgänge im Speicher umwandeln und mehrere Änderungen an einer Seite in einem E/A-Vorgang zusammenführen kann (Löschen der gesamten Seite, sobald sie beschädigt ist). Dadurch wird der Zugriff auf die Festplatte für jeden Lese- und Schreibvorgang vermieden und die Leistung der Datenbank erheblich verbessert.

Persistenzdefinition

Persistenz bedeutet, dass nach der Festschreibung einer Transaktion die an der Datenbank vorgenommenen Änderungen dauerhaft sein sollten und nachfolgende Vorgänge oder Fehler keine Auswirkungen auf die Änderungen dieser Transaktion haben sollten.

Aus der vorherigen Einführung wissen wir, dass InnoDB Buffer Pool verwendet, um die Lese- und Schreibleistung zu verbessern. Der Pufferpool befindet sich jedoch im Speicher und ist flüchtig. Wenn MySQL nach dem Festschreiben einer Transaktion plötzlich abstürzt und die geänderten Daten im Pufferpool zu diesem Zeitpunkt noch nicht auf die Festplatte aktualisiert wurden, gehen Daten verloren und die Persistenz der Transaktion kann nicht garantiert werden.

Um dieses Problem zu lösen, hat InnoDB ein Redo-Log eingeführt, um die Beständigkeit von Datenänderungen zu erreichen. Wenn Daten geändert werden, ändert InnoDB nicht nur die Daten im Pufferpool, sondern zeichnet den Vorgang auch im Redo-Protokoll auf und stellt sicher, dass das Redo-Protokoll früher als die entsprechende Seite auf die Festplatte geschrieben wird (normalerweise, wenn die Transaktion festgeschrieben wird), was häufig als WAL bezeichnet wird. Wenn MySQL plötzlich abstürzt und die Daten nicht auf die Festplatte zurückgeschrieben wurden, verwendet MySQL nach dem Neustart das auf die Festplatte geschriebene Redo-Protokoll, um die Datenseiten wiederherzustellen, die nicht auf die Festplatte zurückgeschrieben wurden.

Implementierungsprinzip: Redo-Log

Um die Leistung zu verbessern, bestehen Redo-Protokolle ähnlich wie Datenseiten aus zwei Teilen: Einer ist der Protokollpuffer im Speicher, der flüchtig ist; der andere ist die Redo-Protokolldatei auf der Festplatte, die dauerhaft ist. Das Redo-Log ist ein physisches Protokoll, das den Status physischer Seiten in der Datenbank aufzeichnet.

Wenn Daten geändert werden, ändert InnoDB nicht nur die Daten im Pufferpool, sondern zeichnet den Vorgang auch im Redo-Log-Puffer auf. Wenn die Transaktion festgeschrieben wird, wird der Redo-Log-Puffer auf die Festplatte geleert und in der Redo-Log-Datei aufgezeichnet. Wenn MySQL abstürzt, können Sie beim Neustart die Daten in der Redo-Log-Datei lesen, um die Datenbank wiederherzustellen. Auf diese Weise müssen die Daten nicht bei jeder Übermittlung einer Transaktion in Echtzeit gelöscht werden.

Schreibprozess

Notiz:

  • Ändern Sie zuerst den Pufferpool und schreiben Sie dann den Redo-Log-Puffer.
  • Das Redo-Log wird vor der Datenseite wieder auf die Festplatte geschrieben: Wenn die Transaktion festgeschrieben wird, wird der Redo-Log-Puffer in die Redo-Log-Datei geschrieben. Das Festschreiben ist nur erfolgreich, wenn der Schreibvorgang erfolgreich ist (es gibt andere Szenarien, die den Schreibvorgang auslösen, die hier nicht näher erläutert werden) und die Daten im Pufferpool werden zu einem späteren Zeitpunkt vom Hintergrundthread auf die Festplatte geschrieben.
  • Beim Löschen fehlerhafter Daten müssen wir sicherstellen, dass das entsprechende Redo-Protokoll auf die Festplatte geschrieben wurde, das sogenannte WAL (Write-Ahead-Protokoll), da sonst die Möglichkeit eines Datenverlusts besteht.

Nutzen

Wenn eine Transaktion festgeschrieben wird, bietet das Schreiben in das Redo-Protokoll gegenüber dem direkten Leeren des Protokolls drei wesentliche Vorteile:

Beim Leeren handelt es sich um zufällige E/A, das Schreiben von Redo-Protokollen hingegen um sequentielle E/A. Sequentielle E/A ist viel schneller als zufällige E/A und nicht erforderlich.
Das Dirty Flushing erfolgt in Einheiten von Datenseiten. Selbst wenn eine Seite nur geringfügig geändert wird, muss die gesamte Seite geschrieben werden. Das Redo-Protokoll enthält nur die tatsächlich geänderten Teile und die Datenmenge ist sehr gering, was ungültige IO stark reduziert.
Beim Leeren von Daten müssen möglicherweise viele Datenseiten geleert werden, und die Atomizität kann nicht garantiert werden (beispielsweise tritt ein Fehler auf, wenn nur ein Teil der Daten geschrieben wird). Der Redo-Log-Puffer schreibt jedoch Protokollblöcke in 512 Bytes in die Redo-Log-Datei, was der Größe eines Sektors entspricht. Der Sektor ist die kleinste Schreibeinheit, sodass garantiert werden kann, dass der Schreibvorgang erfolgreich ist.

Soll ich zuerst das Redo-Protokoll schreiben oder zuerst die Daten ändern?

Ein DML-Vorgang kann Datenänderungen und Redo-Log-Aufzeichnungen umfassen. In welcher Reihenfolge werden sie ausgeführt? In einigen Artikeln im Internet heißt es, dass die Daten zuerst geändert und das Redo-Log später aufgezeichnet werden soll, während in anderen Artikeln gesagt wird, dass das Redo-Log zuerst aufgezeichnet und die Daten später geändert werden sollen. Wie ist also die tatsächliche Situation?

Aus der obigen Beschreibung wissen wir zunächst, dass der Redo-Log-Puffer beim Festschreiben der Transaktion in die Redo-Log-Datei geschrieben wird und das Leeren zu einem späteren Zeitpunkt erfolgt. Daher ist es sicher, dass das Redo-Log zuerst aufgezeichnet und die Datenseite später geändert wird (natürlich wird das WAL-Log zuerst geschrieben).

Die nächste Frage ist, ob zuerst der Redo-Log-Puffer geschrieben oder zuerst der Pufferpool geändert werden soll. Um dieses Problem zu verstehen, müssen wir zunächst den Ausführungsprozess eines DML in InnoDB verstehen. Der Ausführungsprozess eines DML umfasst Datenänderungen, Sperren, Entsperren, Redo-Log-Aufzeichnungen und Undo-Log-Aufzeichnungen, bei denen auch die Atomizität sichergestellt werden muss. InnoDB verwendet MTR (Minitransaktionen), um die Atomizität eines DML-Vorgangs sicherzustellen.

Schauen wir uns zunächst die Definition von MTR an:

Eine interne Phase der InnoDB-Verarbeitung, wenn während DML-Operationen Änderungen auf physischer Ebene an internen Datenstrukturen vorgenommen werden. Bei Minitransaktionen (mtr) gibt es kein Rollback-Konzept; mehrere Minitransaktionen können innerhalb einer einzelnen Transaktion auftreten. Minitransaktionen schreiben Informationen in das Redo-Protokoll, das während der Wiederherstellung nach einem Absturz verwendet wird. Minitransaktionen können auch außerhalb des Kontexts einer regulären Transaktion auftreten, beispielsweise während der Bereinigungsverarbeitung durch Hintergrundthreads. Siehe https://dev.mysql.com/doc/refman/8.0/en/glossary.html

MTR ist eine kurze atomare Operation, die nicht rückgängig gemacht werden kann, da sie selbst atomar ist. Änderungen an Datenseiten müssen über MTR erfolgen, das durch DML-Operationen verursachte Änderungen an Datenseiten im Redo-Protokoll aufzeichnet.

Werfen wir einen kurzen Blick auf den MTR-Prozess:

  • Wenn MTR initialisiert wird, wird eine Kopie von mtr_buf initialisiert
  • Wenn Daten geändert werden, während die Seiten im Speicherpufferpool geändert werden, wird ein Redo-Log-Datensatz generiert und in mtr_buf gespeichert.
  • Wenn die Funktion mtr_commit ausgeführt wird, um den MTR zu committen, wird der Redo-Log-Datensatz in mtr_buf im Redo-Log-Puffer aktualisiert und die schmutzige Seite wird für das nachfolgende Flushing zur Flush-Liste hinzugefügt. Im Protokollpuffer wird jedes Mal, wenn ein 496-Byte-Protokolldatensatz empfangen wird, diese Gruppe von Protokolldatensätzen mit einem 12-Byte-Blockkopf und einem 4-Byte-Blockende umschlossen, sodass ein 512-Byte-Protokollblock entsteht, was für die Ausrichtung von 512 Bytes beim Leeren auf die Festplatte praktisch ist.

Daraus ist ersichtlich, dass InnoDB zuerst den Pufferpool ändert und dann den Redo-Log-Puffer schreibt.

Der Prozess der Datenwiederherstellung

In jedem Fall versucht InnoDB beim Start, Wiederherstellungsvorgänge durchzuführen. Während des Wiederherstellungsvorgangs ist ein Redo-Log erforderlich. Wenn Binlog aktiviert ist, sind auch Binlog und Undo-Log erforderlich. Weil es möglich ist, dass die Daten in das Binärprotokoll geschrieben wurden, die Datenbank jedoch abgestürzt ist, bevor das Redo-Protokoll auf die Festplatte geschrieben wurde (Transaktionen sind eine Funktion der InnoDB-Engine, und geänderte Daten werden möglicherweise nicht festgeschrieben, während das Binärprotokoll eine Funktion der MySQL-Dienstschicht ist, und geänderte Daten werden aufgezeichnet). Zu diesem Zeitpunkt sind das Redo-Protokoll, das Binärprotokoll und das Undo-Protokoll erforderlich, um festzustellen, ob nicht festgeschriebene Transaktionen vorhanden sind, und um die nicht festgeschriebenen Transaktionen rückgängig zu machen oder festzuschreiben.

Nachfolgend finden Sie eine kurze Beschreibung des Vorgangs zur Wiederherstellung von Daten ausschließlich mithilfe von Redo-Protokollen:

  • Suchen Sie beim Starten von InnoDB den Speicherort des aktuellsten Prüfpunkts und verwenden Sie die Prüfpunkt-LSN, um für die Protokollwiederherstellung ein Redo-Protokoll zu finden, das größer als die LSN ist.
  • Wenn die Wiederherstellung mittendrin fehlschlägt, hat dies keine Auswirkungen. Wenn Sie die Wiederherstellung erneut durchführen, können Sie die Wiederherstellung ab der Position des letzten erfolgreich gespeicherten Prüfpunkts fortsetzen.

Wiederherstellungsprozess: Die Fehlerbehebung besteht aus drei Phasen: Analyse, Wiederherstellen und Rückgängigmachen. Die Aufgabe der Analysephase besteht darin, anhand der Informationen im Checkpoint und im Protokoll den Operationsumfang der nachfolgenden Redo- und Undo-Phasen zu bestätigen, die im Checkpoint aufgezeichneten Dirty Page-Set-Informationen über das Protokoll zu korrigieren und die kleinste beteiligte LSN-Position als Startposition RedoLSN des nächsten Redo zu verwenden. Gleichzeitig wird der im Checkpoint aufgezeichnete aktive Transaktionssatz (nicht festgeschriebene Transaktionen) als Rollback-Objekt des Undo-Prozesses korrigiert; die Redo-Phase beginnt mit der durch Analyse erhaltenen RedoLSN und spielt alle Redo-Inhalte im Protokoll erneut ab. Beachten Sie, dass dies auch nicht festgeschriebene Transaktionen umfasst; schließlich führt die Undo-Phase mithilfe der Undo-Informationen ein Rollback aller nicht festgeschriebenen Transaktionen durch. Alle Änderungen, die zurückgesetzt werden müssen, können sequenziell über die PrevLSN des Protokolls gefunden werden. Einzelheiten finden Sie unter http://catkang.github.io/2019/01/16/crash-recovery.html

Was ist LSN?

LSN, auch als Protokollsequenznummer bekannt, ist eine monoton zunehmende 64-Bit-Ganzzahl ohne Vorzeichen. Sowohl das Redo-Log als auch die Datenseiten speichern LSN, die als Grundlage für die Datenwiederherstellung verwendet werden kann. Eine größere LSN gibt an, dass die durch den referenzierten Protokolldatensatz beschriebene Änderung später aufgetreten ist.

Was ist Checkpoint?

Der Prüfpunkt stellt einen Speicherpunkt dar und alle Änderungen an der Datenseite vor diesem Punkt (Protokoll-LSN < Prüfpunkt-LSN) wurden in die Datenträgerdatei geschrieben. InnoDB zeichnet nach jeder Datenträgerbereinigung einen Checkpoint auf und zeichnet die neueste Redo-Log-LSN in der Checkpoint-LSN auf, was für die Bestimmung des Startpunkts bei der Datenwiederherstellung praktisch ist.

Oben finden Sie eine ausführliche Erläuterung des Persistenzimplementierungsprinzips von Transaktionen in MySQL. Weitere Informationen zur Persistenz von MySQL-Transaktionen finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung des Implementierungsprinzips der Transaktionsisolationsstufe in MySQL
  • Detaillierte Erklärung der Syntax und des Prozesses der Ausführung von MySQL-Transaktionen
  • Beschreibung der Standardtransaktionsisolationsebene von MySQL und Oracle
  • Automatischer Commit-Vorgang für MySQL-Transaktionen
  • Allgemeine MySQL-Anweisungen zum Anzeigen von Transaktionen und Sperren
  • MySQL Master-Slave-Synchronisation, Implementierungsprinzip des Transaktions-Rollbacks
  • Detaillierte Analyse von MySQL-Datenbanktransaktionen und -Sperren
  • Wird die Tabelle durch ein Update in einer MySQL-Transaktion gesperrt?
  • Tiefgreifendes Verständnis von verteilten PHP+MySQL-Transaktionen und -Lösungen
  • Wie implementiert MySQL ACID-Transaktionen?
  • Warum MySQL große Transaktionen vermeiden sollte und wie man sie löst

<<:  Vollständige Analyse der Webseitenelemente

>>:  Vue realisiert die Bildschirmanpassung von Großbildschirmseiten

Artikel empfehlen

18 Web-Usability-Prinzipien, die Sie kennen müssen

Sie können über die besten visuellen Designfähigk...

Farbabstimmungstechniken und Effektdarstellung für Beauty- und Styling-Websites

Farbe ist eines der wichtigsten Elemente jeder We...

MySQL-Export ganzer oder einzelner Tabellendaten

Exportieren einer einzelnen Tabelle mysqldump -u ...

Zusammenfassung einiger gängiger Konfigurationen und Techniken von Nginx

Vorwort Dieser Artikel listet mehrere gängige, pr...

Verwenden Sie CSS, um einen 3D-Fotowandeffekt zu erstellen

Verwenden Sie CSS, um eine 3D-Fotowand zu erstell...

Detaillierte Erklärung des Linux-Texteditors Vim

Vim ist ein leistungsstarker Vollbild-Texteditor ...

Zusammenfassung der Konstruktor- und Superwissenspunkte in React-Komponenten

1. Einige Tipps zu mit class in react deklarierte...

Beispiele für die Verwendung des Li-Tags in HTML

Ich möchte den Titel links und das Datum rechts a...

Ergänzender Artikel zur Front-End-Performance-Optimierung

Vorwort Ich habe mir die zuvor veröffentlichten A...