Heim  >  Artikel  >  Datenbank  >  Ausführliche Erläuterung der Funktionen der MySQL-Engine und der InnoDB-Absturzwiederherstellung

Ausführliche Erläuterung der Funktionen der MySQL-Engine und der InnoDB-Absturzwiederherstellung

黄舟
黄舟Original
2017-07-24 13:11:161482Durchsuche

Vorwort

Der größte Unterschied zwischen einem Datenbanksystem und einem Dateisystem besteht darin, dass die Datenbank die Atomizität von Vorgängen sicherstellen kann, selbst wenn die Datenbank ausgefallen ist In der Hälfte der Fälle sind hierfür Datenbankprotokolle und ein vollständiger Absturzwiederherstellungsmechanismus erforderlich. In diesem Artikel wird der Absturzwiederherstellungsprozess von InnoDB sorgfältig analysiert. Der Code basiert auf dem 5.6-Zweig.

Grundkenntnisse

lsn: Es kann als die Anzahl der seit der Erstellung der Datenbank generierten Redo-Protokolle verstanden werden. Je größer die Datenbankaktualisierung, desto mehr kann auch als ein Moment der Erneuerung verstanden werden. Darüber hinaus verfügt jede Datenseite auch über eine LSN, die die LSN zum Zeitpunkt der letzten Änderung darstellt. Je größer der Wert, desto später wurde sie geändert. Beispielsweise ist die LSN der Datenseite A 100, die LSN der Datenseite B ist 200, die Prüfpunkt-LSN ist 150 und die System-LSN ist 300, was bedeutet, dass das aktuelle System auf 300 aktualisiert wurde und die Datenseiten kleiner sind Es wurden mehr als 150 Daten auf die Festplatte geleert, daher müssen sich die neuesten Daten von Seite A auf der Festplatte befinden, die Daten von Seite B jedoch nicht unbedingt, sie befinden sich möglicherweise noch im Speicher.
Redo-Log: Moderne Datenbanken müssen Redo-Logs schreiben. Um beispielsweise ein Datenelement zu ändern, schreiben Sie zuerst das Redo-Log und dann die Daten. Nach dem Schreiben des Redo-Logs wird der Erfolg direkt an den Client zurückgegeben. Obwohl es so aussieht, als ob die Festplatte noch einmal beschrieben wird, wird auf diese Weise die Leistung erheblich verbessert, da zufällige Schreibvorgänge auf die Festplatte (Schreiben von Daten) in sequentielle Schreibvorgänge (Schreiben von Redo-Logs) umgewandelt werden. Wenn die Datenbank hängt, können Sie durch Scannen des Redo-Protokolls herausfinden, welche Datenseiten nicht geleert wurden (vor dem Absturz wurden die Datenseiten möglicherweise nur im Speicher geändert, hatten aber keine Zeit, auf die Festplatte zu schreiben). ), um sicherzustellen, dass die Daten nicht verloren gehen.
Rückgängig-Protokoll: Die Datenbank bietet auch Funktionen, die dem Rückgängigmachen ähneln. Wenn Sie feststellen, dass Sie einige falsche Daten geändert haben, können Sie den Rollback-Befehl verwenden, um den vorherigen Vorgang rückgängig zu machen . Zur Unterstützung dieser Funktion sind Rückgängig-Protokolle erforderlich. Um die Parallelität zu verbessern (derselbe Datensatz, das Lesen durch verschiedene Threads kollidiert nicht, das Lesen und Schreiben kollidiert nicht mit dem Schreiben und Lesen, nur das gleichzeitige Schreiben kollidiert), implementieren alle einen MVCC-ähnlichen Mechanismus. Dies basiert auch auf Rückgängig-Protokollen. Um eine einheitliche Verwaltung zu erreichen, verfügen Rückgängig-Protokolle im Gegensatz zu Redo-Protokollen über entsprechende Datenseiten im Pufferpool, die zusammen mit normalen Datenseiten verwaltet werden. Sie werden auch gemäß den LRU-Regeln aus dem Speicher entfernt und von der Festplatte gelesen später. Wie bei normalen Datenseiten müssen auch für Änderungen an Rückgängig-Seiten zunächst Redo-Protokolle geschrieben werden.
Checkpoint: Der englische Name ist checkpoint. Um die Leistung der Datenbank zu verbessern, wird die Datenseite nicht jedes Mal auf die Festplatte geleert, nachdem der Speicher geändert wurde. Die Datenseiten vor dem Checkpoint werden garantiert auf die Festplatte geleert, sodass die vorherigen Protokolle unbrauchbar werden (aufgrund der Wiederverwertung von InnoDB-Redolog-Protokollen kann dieser Teil des Protokolls zu diesem Zeitpunkt möglicherweise überschrieben werden). auf die Festplatte geleert werden, oder es erfolgt möglicherweise kein Schreiben auf die Festplatte, daher müssen die Protokolle nach dem Checkpoint weiterhin während der Wiederherstellung nach einem Absturz verwendet werden. InnoDB führt regelmäßig Prüfpunkte basierend auf dem Aktualisierungsstatus fehlerhafter Seiten vor und verkürzt so die Zeit für die Wiederherstellung nach einem Datenbankabsturz. Die Prüfpunktinformationen stehen am Anfang der ersten Protokolldatei.
Absturzwiederherstellung: Der Benutzer hat die Daten geändert und eine Erfolgsmeldung erhalten. In diesem Fall wurden die geänderten Daten jedoch möglicherweise nicht platziert Die Datenbank bleibt hängen. Nach dem Neustart muss die Datenbank die geänderten Daten aus dem Protokoll abrufen und neu auf die Festplatte schreiben, um sicherzustellen, dass die Daten des Benutzers nicht verloren gehen. Dieser Prozess des Abrufens von Daten aus dem Protokoll ist die Hauptaufgabe der Wiederherstellung nach einem Absturz und kann auch zu einem Datenbank-Rollforward werden. Natürlich ist es bei der Wiederherstellung nach einem Absturz auch erforderlich, nicht festgeschriebene Transaktionen rückgängig zu machen und erfolglose Transaktionen zu übermitteln. Da für den Rollback-Vorgang die Unterstützung von Undo-Protokollen erforderlich ist und die Integrität und Zuverlässigkeit von Undo-Protokollen durch Redo-Protokolle gewährleistet werden muss, führt die Absturzwiederherstellung zunächst ein Redo-Rollforward und dann ein Undo-Rollback durch.

Lassen Sie uns den Wiederherstellungsprozess nach einem Datenbankabsturz sorgfältig aus der Perspektive des Quellcodes analysieren. Der gesamte Prozess wird in der Engine-Initialisierungsphase (innobase_init) abgeschlossen. Die wichtigste Funktion ist innobase_start_or_create_for_mysql, durch die innodb die Erstellung und Initialisierung einschließlich der Wiederherstellung nach einem Absturz abschließt. Lassen Sie uns zunächst das Rollforward der Datenbank vorstellen.

Redo-Log-Roll-Forward-Datenbank

Die Roll-Forward-Datenbank ist hauptsächlich in zwei Phasen unterteilt. Die erste Phase ist die Protokoll-Scan-Phase. Die Scan-Phase verteilt das Redo-Protokoll entsprechend der Space_ID und der Page_No Datenseite, um sicherzustellen, dass die gleichen Daten an denselben Hash-Bucket verteilt und nach LSN-Größe von klein nach groß sortiert werden. Nachdem der Scan abgeschlossen ist, wird die gesamte Hash-Tabelle durchlaufen und die Protokolle jeder Datenseite werden nacheinander angewendet. Nach der Anwendung wird der Status der Datenseite zumindest auf den Zustand vor dem Absturz zurückgesetzt. Lassen Sie uns den Code im Detail analysieren.
Öffnen Sie zunächst alle ibdata-Dateien (open_or_create_data_files) (jede ibdata-Datei kann einen Flush_lsn im Header haben, da ibdata möglicherweise auch Daten enthält). ist nicht vollständig und muss wiederhergestellt werden (recv_recovery_from_checkpoint_start_func) ermittelt durch Vergleich von checkpont_lsn und diesen beiden Werten, ob die ibdata aktualisiert werden muss.
Als nächstes öffnen Sie alle Dateien im Systemtabellenbereich und Protokolltabellenbereich (fil_open_log_and_system_tablespace_files), um unzureichende Dateihandles zu verhindern und den Pufferpool zu löschen (buf_pool_invalidate). Geben Sie als Nächstes die Kernfunktion ein: recv_recovery_from_checkpoint_start_func. Beachten Sie, dass sie auch dann eingegeben wird, wenn die Datenbank normal geschlossen ist.
Obwohl recv_recovery_from_checkpoint_start_func in der Vergangenheit ausführlich wirkte, wurde viel Code für die LOG_ARCHIVE-Funktion geschrieben und es gibt nicht viel Code für die Wiederherstellung nach einem echten Datenabsturz.
Initialisieren Sie zunächst einige Variablen und überprüfen Sie die Variable srv_force_recovery. Wenn der Benutzer festlegt, dass die Rollforward-Phase übersprungen werden soll, kehrt die Funktion direkt zurück.
Als nächstes initialisieren Sie die recv_sys-Struktur, weisen die Größe von hash_table zu und initialisieren die Flush-Liste rbtree. recv_sysDie Struktur wird hauptsächlich in der Roll-Forward-Phase der Unfallwiederherstellung verwendet. hash_table ist die Hash-Tabelle, die zum Speichern von Protokollen verschiedener Datenseiten verwendet wird. Die Größe der Hash-Tabelle wird auf buffer_size_in_bytes/512 initialisiert. Wenn sie die Länge überschreitet, kann sie nicht gespeichert werden Glücklicherweise muss die Anzahl der Datenseiten nicht überschritten werden, da die Pufferabfrage (verschmutzte Seiten, die vor dem Datenbankabsturz online waren) nur buffer_size_in_bytes/16 KB Datenseiten speichern kann betragen höchstens buffer_size_in_bytes/1 KB. Informationen zur Größe dieser Hash-Tabellen-Speicherzuordnung finden Sie unter Fehlernummer 53122. Die Flush-Liste rbtree wird hauptsächlich zum Hinzufügen der eingefügten Dirty-Page-Liste verwendet. Die Flush-Liste muss von klein nach groß nach der ältesten Änderungs-LSN (oldest_modifcation) der Datenseite sortiert werden. Wenn die Datenbank normal ausgeführt wird, können Sie log_sys- verwenden. >mutex und log_sys- >log_flush_order_mutex garantieren die Reihenfolge. Bei der Wiederherstellung nach einem Absturz gibt es keine Garantie dafür, dass die Datenseiten von klein nach groß sortiert werden Gemäß der ältesten Änderung lsn (oldest_modifcation) ist es daher erforderlich, die Flush_list linear zu durchlaufen, um die Einfügeposition zu finden, was zu ineffizient ist. Daher wird ein Rot-Schwarz-Baum eingeführt, um die Suche nach der Einfügeposition zu beschleunigen.
Als nächstes lesen Sie die Checkpoint-Informationen aus dem Header von ib_logfile0, hauptsächlich einschließlich checkpoint_lsn und checkpoint_no. Da InnoDB-Protokolle zyklisch verwendet werden und es mindestens 2 geben muss, muss ib_logfile0 vorhanden sein. Es ist sicher, Prüfpunktinformationen darin zu speichern, und es besteht kein Grund zur Sorge, gelöscht zu werden. Die Prüfpunktinformationen werden tatsächlich an zwei Stellen im Dateikopf geschrieben, und die beiden Prüfpunktfelder werden nacheinander geschrieben. Warum müssen wir abwechselnd an zwei Stellen schreiben? Angenommen, es gibt nur ein Prüfpunktfeld und dieses Feld wird ständig aktualisiert, und das Prüfpunktfeld hat 512 Bytes (OS_FILE_LOG_BLOCK_SIZE). Wenn nur diese 512 Bytes geschrieben werden, hängt die Datenbank auf und auch der Server hängt (). (ohne Berücksichtigung der Atomizität der Hardware) Schreibfunktion (frühe Hardware verfügt nicht über diese Funktion), möglicherweise wird nur die Hälfte der 512 Bytes geschrieben, was dazu führt, dass die gesamte Prüfpunktdomäne nicht verfügbar ist. Auf diese Weise kann die Datenbank keine Wiederherstellung nach einem Absturz durchführen und kann daher nicht gestartet werden. Wenn zwei Prüfpunktdomänen vorhanden sind, können Sie, selbst wenn eine beschädigt ist, immer noch die andere zur Wiederherstellung verwenden. Obwohl das Protokoll zu diesem Zeitpunkt möglicherweise überschrieben wurde, erhöht es zumindest die Wahrscheinlichkeit einer erfolgreichen Wiederherstellung. Die beiden Prüfpunktdomänen werden nacheinander geschrieben, wodurch auch die Auswirkungen von Festplattensektorausfällen verringert werden können. Die Datenseiten vor checkpoint_lsn wurden auf der Festplatte abgelegt und müssen nicht aktualisiert werden. Die nachfolgenden Datenseiten wurden möglicherweise noch nicht auf der Festplatte abgelegt und müssen wiederhergestellt werden. Es spielt keine Rolle, ob sie auf der Festplatte abgelegt wurden Da das Redo-Log idempotent ist, wird es trotzdem einmal angewendet und zweimal angewendet (zugrunde liegende Implementierung: Wenn die LSN auf der Datenseite größer oder gleich der LSN des aktuellen Redo-Logs ist, wird sie andernfalls nicht angewendet Unter checkpoint_no versteht man die Häufigkeit, mit der die Checkpoint-Domäne auf die Festplatte geschrieben wird. Jedes Mal, wenn die Festplatte geleert wird, wird dieser Wert modulo 2 verwendet, um alternatives Schreiben zu implementieren Das Feld checkpoint_no. Unter normaler Logik wird der Wert von checkpoint_no als endgültige Checkpoint-Information ausgewählt, die als Ausgangspunkt für nachfolgende Crash-Recovery-Scans verwendet wird.Nachdem wir die Informationen im Prüfpunktfeld verwendet haben, um einige Informationen in der Struktur recv_sys zu initialisieren, geben wir die Kernfunktion der Protokollanalyse ein. Wir werden diese Funktion später analysieren Wenn dies nicht ausreicht, wird die Anwendung direkt aufgerufen (recv_group_scan_log_recs) und dann mit der Analyse fortfahren. Wenn nur sehr wenige Protokolle angewendet werden müssen, analysieren Sie einfach das Verteilungsprotokoll und wenden Sie das Protokoll in der Funktion recv_apply_hashed_log_recs an. recv_recovery_from_checkpoint_finishFühren Sie als Nächstes einen Prüfpunkt basierend auf dem aktuellen Status der geleerten Datenseite durch, da möglicherweise einige Protokolle in
angewendet wurden. An diesem Punkt endet die recv_group_scan_log_recs-Funktion. recv_recovery_from_checkpoint_start_funcWenn in der Funktion
die Einstellung srv_force_recovery korrekt ist, rufen Sie die Funktion recv_recovery_from_checkpoint_finish auf, um das Protokoll anzuwenden, warten Sie dann, bis der Dirty-Thread beendet wird (der Thread wird während der Wiederherstellung nach einem Absturz vorübergehend gestartet) und schließlich Geben Sie die zugehörigen Ressourcen von recv_sys und den von hash_table belegten Speicher frei. recv_apply_hashed_log_recsAn diesem Punkt ist der Datenbank-Rollforward abgeschlossen. Als nächstes analysieren wir die Implementierungsdetails der Redo-Log-Analysefunktion und der Redo-Log-Anwendungsfunktion im Detail.

Redo-Log-Parsing-Funktion

Die oberste Ebene der Parsing-Funktion ist

. Diese Funktion ruft die zugrunde liegende Funktion auf (recv_group_scan_log_recs) und liest Stapel entsprechend der Größe von RECV_SCAN_SIZE (. 64 KB). Beurteilen Sie nach dem Auslesen zunächst anhand der Beziehung zwischen block_no und lsn und der Protokollprüfsumme, ob das Ende des Protokolls gelesen wurde (damit ersichtlich ist, dass im Protokollkopf keine Markierung vorhanden ist, um die effektive Position des Protokolls zu markieren). , und es wird vollständig anhand der beiden oben genannten Bedingungen beurteilt, ob das Ende des Protokolls erreicht ist, und es wird zurückgegeben, wenn es bis zum Ende gelesen wird (wie bereits erwähnt, muss die Absturzwiederherstellungslogik verwendet werden, auch wenn die Datenbank normal geschlossen ist). Daher wird es hier zurückgegeben, da der Prüfpunktwert des normalen Herunterfahrens auf das Ende des Protokolls zeigen muss. Andernfalls entfernen Sie den Anfang und das Ende des Protokolls und fügen Sie einige Kontrollinformationen und Prüfsummen in einen recv_sys->buf ein Im Protokollkopf werden Werte gespeichert, die nur zur Überprüfung und Positionierung dienen und in realen Anwendungen nutzlos sind. Bevor Sie es in recv_sys->buf platzieren, müssen Sie prüfen, ob recv_sys->buf voll ist (log_group_read_log_seg, 2M). Wenn es voll ist, wird ein Fehler gemeldet (wenn der vorherige Analysestapel unvollständige Protokolle enthält). , verteilt die Protokollanalysefunktion diese unvollständigen Protokolle nicht, sondern belässt sie in recv_sys->buf, bis das vollständige Protokoll analysiert ist. Als nächstes analysieren Sie das Protokoll von recv_sys->buf (RECV_PARSING_BUF_SIZE). Es gibt zwei Arten von Protokollen: single_rec und multi_rec. Ersteres bedeutet, dass nur eine Operation auf einer Datenseite ausgeführt wird, und letzteres bedeutet, dass mehrere Operationen auf einer oder mehreren Datenseiten ausgeführt werden. Das Protokoll enthält außerdem die space_id, page_no der entsprechenden Datenseite, die Art der Operation und den Inhalt der Operation (recv_parse_log_recs). Nachdem Sie das entsprechende Protokoll analysiert haben, hashen Sie es gemäß space_id und page_no (wenn der entsprechende Tabellenbereich nicht im Speicher vorhanden ist, bedeutet dies, dass die Tabelle gelöscht wurde) und legen Sie es in hash_table (dem tatsächlichen Speicherort des Protokolls) ab befindet sich immer noch im Pufferpool) Das war's und wartet auf nachfolgende Anwendungen. Hier sind einige Punkte zu beachten: recv_parse_log_rec

  • Wenn es sich um einen multi_rec-Typ handelt, gilt das Protokoll nur dann als vollständig, wenn die Markierung MLOG_MULTI_REC_END angetroffen wird, und wird an die hash_table verteilt. Wenn wir uns den Code ansehen, können wir feststellen, dass das Protokoll vom Typ multi_rec zweimal analysiert wird, einmal, um die Integrität zu überprüfen (nach MLOG_MULTI_REC_END zu suchen), und das zweite Mal, um das Protokoll zu verteilen. Ich bin der Meinung, dass dies ein Punkt ist, der optimiert werden kann.

  • Derzeit gibt es mehr als 50 Protokolloperationstypen. Der Inhalt hinter jeder Operation ist unterschiedlich, daher ist auch die Länge unterschiedlich. Die aktuelle Protokollanalyselogik muss alle Protokolle analysieren Sequenzinhalt und bestimmen Sie dann die Länge, um die Startposition des nächsten Protokolls zu ermitteln. Diese Methode ist etwas ineffizient. Tatsächlich können Sie dem Header jedes Vorgangs ein Feld hinzufügen, um die Länge des nachfolgenden Inhalts zu speichern. Auf diese Weise müssen Sie nicht zu viel Inhalt analysieren, wodurch die Analysegeschwindigkeit verbessert wird Den Ergebnissen zufolge kann die Geschwindigkeit verdoppelt werden (von 38 Sekunden auf 14 Sekunden, siehe Fehler Nr. 82937).

  • Wenn Sie feststellen, dass nach dem Prüfpunkt noch Protokolle vorhanden sind, bedeutet dies, dass die Datenbank zuvor nicht ordnungsgemäß heruntergefahren wurde und eine Wiederherstellung nach einem Absturz durchgeführt werden muss, sodass Sie einige zusätzliche Vorgänge ausführen müssen ( recv_init_crash_recovery), wie zum Beispiel das Drucken unserer häufigen Fehler im Fehlerprotokoll „Datenbank wurde nicht normal heruntergefahren!“ und „Absturzwiederherstellung wird gestartet.“ Außerdem müssen Sie überprüfen, ob die Datenseite zur Hälfte aus dem doppelten Schreibpuffer geschrieben wurde. Wenn eine Wiederherstellung erforderlich ist (buf_dblwr_process), müssen Sie auch einen Thread zum Flushen der vom Anwendungsprotokoll generierten schmutzigen Seiten starten (da buf_flush_page_cleaner_thread zu diesem Zeitpunkt noch nicht gestartet wurde). Abschließend müssen alle Tabellenbereiche geöffnet werden. . Beachten Sie, dass es sich ausschließlich um Tabellen handelt. . . Beim Betrieb und der Wartung von Alibaba Cloud RDS MySQL stellen wir häufig fest, dass die Datenbank in der Wiederherstellungsphase nach einem Absturz hängen bleibt und im Fehlerprotokoll ähnliche Wörter wie „Lesen von Tablespace-Informationen aus den .ibd-Dateien ...“ vorhanden sind dass die Datenbank alle Tabellen öffnet, und als ich mir dann die Anzahl der Tabellen ansah, stellte ich fest, dass es Dutzende oder sogar Millionen von Tabellen gibt. . . Der Grund, warum die Datenbank alle Tabellen öffnen muss, liegt darin, dass beim Verteilen von Protokollen ermittelt werden muss, welcher IBD-Datei die Space_ID entspricht. Dies wird durch Öffnen aller Tabellen und Lesen der Space_ID-Informationen ermittelt Puffer zur Überprüfung halb geschriebener Daten. Um das Problem zu lösen, dass zu viele Tabellen zu einer zu langsamen Wiederherstellung führen, wurde MySQL 5.7 optimiert, WL#7142. Die Hauptidee besteht darin, ein neues Protokoll mlog_file_name (einschließlich Zuordnung von space_id und Dateiname) zu schreiben, um anzuzeigen, dass eine Operation durchgeführt wurde Nachfolgende Vorgänge für diese Tabelle erfordern kein Schreiben dieses neuen Protokolls. Wenn eine Wiederherstellung nach einem Absturz erforderlich ist, kann ein weiterer Scan durchgeführt werden, um festzustellen, welche Tabellen geändert wurden, sodass kein Öffnen erforderlich ist alle Tabellen, um space_id zu bestimmen.

  • Das Letzte, was erwähnenswert ist, ist die Erinnerung. Wenn, wie bereits erwähnt, zu viele Protokolle verteilt wurden und zu viel Speicher belegen, wendet die Protokollanalysefunktion die Protokolle zum richtigen Zeitpunkt an, anstatt bis zum Ende zu warten, um sie alle zusammen anzuwenden. Dann stellt sich die Frage, wie viel Speicher verbraucht wird, bevor die Protokollierungslogik angewendet wird. Die Antwort lautet: buffer_pool_size_in_bytes – 512 * buffer_pool_instance_num * 16 KB. Da buffer_pool_instance_num im Allgemeinen nicht zu groß ist, kann der größte Teil des Speichers im Pufferpool zum Speichern von Protokollen verwendet werden. Die verbleibenden Datenseiten sind hauptsächlich für die Datenseiten reserviert, die beim Anwenden des Protokolls gelesen werden, da die Protokollanwendung derzeit Single-Threaded ist. Das Lesen eines Protokolls, das Anwenden aller Protokolle und das Zurückspülen auf die Festplatte erfordert nicht viel der Erinnerung.

Redo-Log-Anwendungsfunktion

Die obere Funktion des Anwendungsprotokolls ist recv_apply_hashed_log_recs (das Anwendungsprotokoll kann auch in der io_helper-Funktion ausgeführt werden). Durchlaufen Sie hash_table, wenden Sie bei Festplattenlesevorgängen die Protokolle in den Hash-Buckets nacheinander auf jede Datenseite an. Nachdem Sie alle Protokolle angewendet haben, leeren Sie bei Bedarf alle buffer_pool-Seiten. Schließlich ist der Speicherplatz begrenzt. Folgende Punkte sind zu beachten:

  • Protokolle auf derselben Datenseite müssen gemäß lsn von klein nach groß angewendet werden, andernfalls werden die Daten überschrieben. Wenden Sie nur Redo-Protokolle an, deren lsn größer als page_lsn ist. Nur diese Protokolle müssen erneut erstellt werden, der Rest wird ignoriert. Fügen Sie nach dem Anwenden des Protokolls die schmutzige Seite zur Liste der schmutzigen Seiten hinzu. Da die Liste der schmutzigen Seiten nach der ältesten Änderungs-LSN (oldest_modification) sortiert ist, wird hier ein rot-schwarzer Baum eingeführt, um die Suche nach der Einfügeposition zu beschleunigen. Die zeitliche Komplexität ist im Vergleich zu früher gestiegen. Die lineare Suche ist auf die logarithmische Ebene reduziert.

  • Wenn eine bestimmte Datenseite benötigt wird und sich herausstellt, dass sie sich nicht im Pufferpool befindet, werden die 32 Datenseiten rund um diese Datenseite überprüft, um festzustellen, ob eine Wiederherstellung ebenfalls erfolgt Wenn ja, können sie zusammen ausgelesen werden, was einem IO-Merge und einer Reduzierung der IO-Operationen entspricht (recv_read_in_area). Da es sich um einen asynchronen Lesevorgang handelt, übernimmt der io_helper-Thread (buf_page_io_complete) die letzte Arbeit am Anwendungsprotokoll. Um zu verhindern, dass in kurzer Zeit zu viele IOS initiiert werden, wird dem Code außerdem eine Flusskontrolllogik hinzugefügt (buf_read_recv_pages). Wenn festgestellt wird, dass sich eine Datenseite im Speicher befindet, wird das Anwendungsprotokoll recv_recover_page direkt aufgerufen. Daraus können wir erkennen, dass es sich beim InnoDB-Anwendungsprotokoll nicht um ein Single-Thread-Anwendungsprotokoll handelt. Zusätzlich zum Hauptthread für die Wiederherstellung nach einem Absturz ist auch der io_helper-Thread an der Wiederherstellung beteiligt. Die Anzahl der gleichzeitigen Threads hängt von der Anzahl der Lesethreads in io_helper ab.

Nachdem die Redo-Rollforward-Datenbank ausgeführt wurde, befinden sich alle Datenseiten der Datenbank bereits in einem konsistenten Zustand und die Undo-Rollback-Datenbank kann sicher ausgeführt werden. Wenn die Datenbank abstürzt, gibt es möglicherweise einige nicht festgeschriebene oder festgeschriebene Transaktionen. Zu diesem Zeitpunkt müssen Sie entscheiden, ob Sie festschreiben möchten. Es ist hauptsächlich in drei Schritte unterteilt: Scannen Sie zunächst das Rückgängig-Protokoll und stellen Sie die verknüpfte Liste des Rückgängig-Protokolls wieder her. Rekonstruieren Sie dann die Transaktion vor dem Absturz, dh stellen Sie den Status wieder her der Transaktion zu diesem Zeitpunkt. Abschließend wird je nach Status der Transaktion ein Rollback oder Commit durchgeführt.

Protokoll-Rollback-Datenbank rückgängig machen

wird nach recv_recovery_from_checkpoint_start_func und vor recv_recovery_from_checkpoint_finish aufgerufen. Diese Funktion führt die ersten beiden der oben genannten drei Schritte aus. trx_sys_init_at_db_startDer erste Schritt wird in der Funktion
verarbeitet, die den gesamten Rückgängig-Protokollbereich durchläuft (bis zu TRX_SYS_N_RSEGS (128) Segmente). Wenn festgestellt wird, dass ein Rückgängig-Segment nicht leer ist, wird es initialisiert (trx_rseg_array_init). ). Wenn für jedes Rückgängig-Segment festgestellt wird, dass der Rückgängig-Slot nicht leer ist (bis zu TRX_RSEG_N_SLOTS (1024) Slots), wird er initialisiert (trx_rseg_create_instance). Fügen Sie nach der Initialisierung des Undo-Slots verschiedene Arten von Undo-Protokollen in verschiedene verknüpfte Listen ein (trx_undo_lists_init). Es gibt zwei Haupttypen von Rückgängig-Protokollen: TRX_UNDO_INSERT und TRX_UNDO_UPDATE. Ersteres wird hauptsächlich für Einfügevorgänge verwendet, und letzteres wird für Aktualisierungs- und Löschvorgänge verwendet. Wie bereits erwähnt, hat das Rückgängig-Protokoll zwei Funktionen: Es wird beim Zurücksetzen von Transaktionen und beim Lesen von MVCC-Snapshots verwendet. Da die Einfügedaten nicht für andere Threads bereitgestellt werden müssen, kann das Rückgängig-Protokoll vom Typ TRX_UNDO_INSERT gelöscht werden, solange die Transaktion festgeschrieben wird. TRX_UNDO_UPDATE kann nicht gelöscht werden, nachdem die Transaktion festgeschrieben wurde. Es muss sichergestellt werden, dass kein Snapshot es verwendet, bevor es durch den Hintergrundbereinigungsthread bereinigt werden kann. trx_undo_mem_create_at_db_startDer zweite Schritt wird in der Funktion
ausgeführt. Da im ersten Schritt undo_insert_list und undo_update_list im Speicher erstellt wurden (jedes Rückgängig-Segment der verknüpften Liste ist unabhängig), muss dieser Schritt nur durchlaufen werden alle verknüpften Listen und erstellen Sie sie neu. Der Status der Transaktion (trx_lists_init_at_db_start und trx_resurrect_insert). Einfach ausgedrückt: Wenn der Status des Rückgängig-Protokolls TRX_UNDO_ACTIVE ist, ist der Status der Transaktion TRX_ACTIVE. Wenn der Status des Rückgängig-Protokolls TRX_UNDO_PREPARED ist, ist der Status der Transaktion TRX_PREPARED. Hier sollte auch die Einstellung der Variablen srv_force_recovery berücksichtigt werden. Wenn der Wert dieser Variablen nicht 0 ist, werden alle Transaktionen zurückgesetzt (d. h. die Transaktion wird auf TRX_ACTIVE gesetzt), auch wenn der Status der Transaktion sein sollte TRX_STATE_PREPARED. Nachdem die Transaktion neu erstellt wurde, wird sie entsprechend der Transaktions-ID zur verknüpften Liste trx_sys->trx_list hinzugefügt. Schließlich zählt die Funktion trx_resurrect_update, wie viele Datenzeilen für alle rückgängig zu machenden Transaktionen zurückgesetzt werden müssen (der Transaktionsstatus ist TRX_ACTIVE), und gibt sie im Fehlerprotokoll aus, ähnlich wie: 5 Transaktionen, die zurückgesetzt oder bereinigt werden müssen. InnoDB: Insgesamt müssen 342232 Zeilenoperationen rückgängig gemacht werden. trx_sys_init_at_db_startDer dritte Schritt wird an zwei Stellen aufgerufen. Einer befindet sich am Ende von
und der andere in recv_recovery_from_checkpoint_finish. Ersteres dient hauptsächlich dazu, den Vorgang des Datenwörterbuchs zurückzusetzen, dh den Vorgang des Zurücksetzens der DDL-Anweisung, und letzteres dient dazu, die DML-Anweisung zurückzusetzen. Ersteres muss abgeschlossen sein, bevor die Datenbank Dienste bereitstellen kann, während letzteres fortgesetzt werden kann, nachdem die Datenbank Dienste bereitgestellt hat (d. h. die Wiederherstellung nach einem Absturz abgeschlossen ist) (verarbeitet durch Öffnen eines neuen Hintergrundthreads recv_recovery_rollback_active). Da InnoDB der Ansicht ist, dass das Datenwörterbuch das Wichtigste ist, muss es auf einen konsistenten Zustand zurückgesetzt werden. Die Daten in der Benutzertabelle können etwas langsamer sein und nach der Bereitstellung externer Dienste langsam wiederhergestellt werden. Daher stellen wir häufig fest, dass die Datenbank gestartet wurde und das Fehlerprotokoll dann immer noch Rollback-Transaktionsinformationen druckt. Die Kernfunktion des Transaktions-Rollbacks ist trx_rollback_or_clean_all_recovered. Sie müssen nur trx_sys->trx_list durchlaufen und je nach Status der Transaktion ein Rollback durchführen oder senden (trx_rollback_or_clean_recovered). Hierbei ist zu beachten, dass, wenn sich die Transaktion im Status TRX_STATE_PREPARED befindet, keine Verarbeitung auf der InnoDB-Ebene durchgeführt wird. Die Serverebene muss basierend auf der Binlog-Situation entscheiden, ob die Transaktion zurückgesetzt werden soll , wird die Transaktion übermittelt, da das Binlog in die Standby-Datenbank übertragen wurde. Wenn die Primärdatenbank zurückgesetzt wird, sind die Primär- und Standby-Daten inkonsistent zurückgerollt. trx_rollback_resurrected

Crash-Recovery-bezogene Parameteranalyse

innodb_fast_shutdown: innodb_fast_shutdown = 0. Dies bedeutet, dass beim Herunterfahren von MySQL ein langsames Herunterfahren durchgeführt wird, das nicht nur das Leeren des Protokolls und das Leeren der Datenseiten umfasst, sondern auch Datenbereinigung (Purge), ibuf-Zusammenführung, Pufferpool-Dump und Lazy-Table-Drop-Vorgänge (sofern vorhanden). Tabelle Es sind noch nicht abgeschlossene Vorgänge vorhanden. Auch wenn die Tabelle gelöscht wird und die Rückgabe erfolgreich ist, wird die Tabelle möglicherweise nicht sofort gelöscht.
innodb_fast_shutdown = 1. Dies ist der Standardwert, was bedeutet, dass beim Herunterfahren von MySQL nur die Protokolle und Daten geleert werden.
innodb_fast_shutdown = 2. Das bedeutet, dass beim Schließen nur die Protokolle geleert werden und nichts anderes geschieht, als ob MySQL abgestürzt wäre.
Je größer der Wert dieses Parameters ist, desto schneller wird MySQL heruntergefahren, aber desto langsamer ist die Startgeschwindigkeit, was gleichbedeutend damit ist, dass die Arbeit, die beim Herunterfahren erledigt werden muss, auf die Wiederherstellung nach einem Absturz verlagert wird. Wenn MySQL aktualisiert werden soll, wird außerdem empfohlen, die erste Methode zu verwenden, um ein sauberes Herunterfahren durchzuführen.

innodb_force_recovery:
Dieser Parameter wird hauptsächlich verwendet, um zu steuern, welche Arbeit InnoDB beim Start ausführt. Je größer der Wert, desto weniger Arbeit wird geleistet und der Start ist einfacher , aber die Daten Das Risiko einer Inkonsistenz ist auch größer. Wenn MySQL aus unkontrollierbaren Gründen nicht gestartet werden kann, können Sie diesen Parameter festlegen und ihn schrittweise von 1 erhöhen, bis MySQL startet, und dann SELECT INTO OUTFILE verwenden, um die Daten zu exportieren und Ihr Bestes zu geben, um den Datenverlust zu reduzieren.
innodb_force_recovery = 0. Dies ist der Standardparameter, wenn er gestartet wird, einschließlich der Redo-Log-Anwendung, des Rückgängigmachens des Log-Rollbacks, des Startens der Hintergrund-Master- und Purge-Threads und der ibuf-Zusammenführung. Es wird festgestellt, dass die Datenseite beschädigt ist. Wenn sie sich im Systemtabellenbereich befindet, wird ein Fehlerprotokoll protokolliert.
innodb_force_recovery = 1. Wenn festgestellt wird, dass die Datenseite beschädigt ist, kommt es zu keinem Absturz oder Fehler (buf_page_io_complete) und die Richtigkeit der ersten Datenseite des Tabellenbereichs wird beim Start nicht überprüft (fil_check_first_page). Auf den Tabellenbereich kann nicht zugegriffen werden (fil_open_single_table_tablespace, fil_load_single_table_tablespace), ddl-Vorgänge können nicht ausgeführt werden (check_if_supported_inplace_alter) und die Datenbank kann auch keine Schreibvorgänge ausführen (row_insert_for_mysql, row_update_for_mysql). usw.) und alle Vorbereitungstransaktionen werden ebenfalls zurückgesetzt (trx_resurrect_insert, trx_resurrect_update_in_prepared_state). Diese Option wird immer noch sehr häufig verwendet. Wenn die Datenseite aufgrund einer fehlerhaften Festplatte beschädigt ist, kann sichergestellt werden, dass die Datenbank normal startet.
innodb_force_recovery = 2. Zusätzlich zu den Vorgängen nach Einstellung 1 werden die Hintergrund-Master- und Purge-Threads nicht gestartet (srv_master_thread, srv_purge_coordinator_thread usw.). Wenn Sie feststellen, dass die Datenbank aufgrund dieser beiden Threads nicht gestartet werden kann, können Sie dies tun Satz .
innodb_force_recovery = 3. Abgesehen davon, dass Vorgänge nach Einstellung 2 nicht ausgeführt werden, wird kein Rückgängig-Rollback der Datenbank durchgeführt, das Rollback-Segment wird jedoch weiterhin gescannt und die verknüpfte Rückgängig-Liste wird weiterhin erstellt (trx_sys_init_at_db_start). srv_read_only_mode wird aktiviert.
innodb_force_recovery = 4. Darüber hinaus werden die Vorgänge nach Einstellung 3 nicht ausgeführt, der ibuf-Vorgang wird nicht ausgeführt (ibuf_merge_or_delete_for_page) und der Thread für Tabelleninformationsstatistiken wird nicht ausgeführt (da eine fehlerhafte Indexseite zum Absturz der Datenbank führt) (info_low, dict_stats_updateusw.). Ab dieser Option führen alle nachfolgenden Optionen zu Datenschäden. Gehen Sie daher mit Vorsicht vor.
innodb_force_recovery = 5. Darüber hinaus werden die Vorgänge nach Einstellung 4 nicht ausgeführt, das Rollback-Segment wird nicht gescannt (recv_recovery_rollback_active) und die Rückgängig-verknüpfte Liste wird nicht erstellt. Dies wird hauptsächlich verwendet, wenn das Rückgängig-Protokoll fehlerhaft geschrieben ist.
innodb_force_recovery = 6. Zusätzlich zu den Vorgängen nach Einstellung 5 werden Datenbank-Rollforward-Vorgänge nicht ausgeführt, einschließlich Parsen und Anwenden (recv_recovery_from_checkpoint_start_func).

Zusammenfassung

InnoDB hat einen vollständigen Absturzwiederherstellungsmechanismus implementiert, um sicherzustellen, dass die Datenbank normal wiederhergestellt werden kann, wenn sie in einem beliebigen Zustand hängt (einschließlich Absturzwiederherstellungsstatus). Der größte Unterschied im System. Darüber hinaus nutzt die Crash-Recovery physische Protokolle wie Redo-Logs, um Datenseiten anzuwenden, was der MySQL-Replikation neue Ideen verleiht. Kann die Standby-Datenbank Daten auf ähnliche Weise synchronisieren wie die Anwendung von Redo-Logs? Das Alibaba Cloud RDS MySQL-Team wird Ihnen in nachfolgenden Produkten ähnliche Funktionen bieten, also bleiben Sie auf dem Laufenden.

Das obige ist der detaillierte Inhalt vonAusführliche Erläuterung der Funktionen der MySQL-Engine und der InnoDB-Absturzwiederherstellung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn