VorwortAls ich zum ersten Mal von der Implementierung von MySQL erfuhr, hörte ich immer Schlüsselwörter wie Redo-Log, WAL (Write-Ahead-Logging) und Undo-Log. Ich erfuhr, dass Redo-Log hauptsächlich verwendet wird, um Transaktionspersistenz zu erreichen. Um das Redo-Protokoll besser zu verstehen, habe ich mir den entsprechenden Code angesehen (Quellcodeversion: MySQL 8.0.12). Hier ist eine kurze Zusammenfassung, die hauptsächlich erklärt, wie das Redo-Protokoll generiert wird, wie es auf die Festplatte geschrieben wird und wie der Benutzer schließlich benachrichtigt wird. Generierung eines Redo-LogsWährend der Ausführung von Lese-/Schreibtransaktionen werden kontinuierlich Redo-Protokolle generiert. Das Beantragen von Datenseiten, Ändern von Datenseiten, Aufzeichnen von Undo-Protokollen usw. führt zur Generierung von Redo-Protokollen. MySQL teilt Benutzertransaktionen in MTRs (Minitransaktionen) auf. Wenn das Redo-Protokoll zum ersten Mal generiert wird, wird es im MTR aufgezeichnet und zusammen mit der Übermittlung des MTR festgeschrieben und landet schließlich auf der Festplatte. Redo-Log-ÜbermittlungWenn mtr übermittelt wird, wird das Redo-Protokoll in mtr in den Protokollpuffer der Systemvariable log_sys geschrieben. Eine neue Funktion von MySQL 8.0 ist die sperrenfreie Redo-Log-Übermittlung. Vor 8.0 konkurrierte jeder Benutzer-Thread um Mutexe und schrieb seriell in den Protokollpuffer. Dadurch wurde sichergestellt, dass die LSN sequenziell und ohne Lücken wuchs. In 8.0 können Benutzerthreads gleichzeitig in den Protokollpuffer schreiben. Wenn ein Benutzerthread erfolgreich in den Protokollpuffer schreibt und dann den Protokollpuffer leert, bevor die LSN auf die Festplatte geschrieben wurde, kann dies dazu führen, dass andere Benutzerthreads den Protokollpuffer leeren, bevor sie mit dem Schreiben fertig sind. Um dieses Problem zu lösen, wurde in MySQL 8.0 die Datenstruktur Link_buf eingeführt, um Löcher im Protokollpuffer zu vermeiden. Link_buf ist eigentlich ein Array mit fester Länge, das den Schreibstatus eines Abschnitts des Protokollpuffers wie ein gleitendes Fenster verfolgt und sich vorwärts bewegt, während kontinuierliche Redo-Protokolle in den Protokollpuffer geschrieben werden. Die Datenstruktur von Link_buf ist wie folgt: Wenn der Benutzer das Redo-Protokoll zwischen start_lsn und end_lsn in den Protokollpuffer schreibt, wird die entsprechende Position von Link_buf markiert, d. h. m_link[start_lsn%m_capacity] wird der Wert end_lsn-start_lsn zugewiesen. Der Vorgang der Redo-Log-Aufzeichnung im Log-Puffer läuft wie folgt ab: 1. Wenn jeder Benutzer-Thread ein Redo-Protokoll schreibt, erhält er zunächst die Start- und End-LSN des Redo-Protokolls aus der globalen atomaren Systemvariable log_sys.sn entsprechend der Länge des Redo-Protokolls. Die atomare Variable sn kann sicherstellen, dass das von jedem Thread erhaltene start_lsn-end_lsn-Intervall kontinuierlich und ohne Lücken ist. 2. Nachdem der Benutzer-Thread das Intervall start_lsn-end_lsn beantragt hat, muss er warten, bis Link_buf an eine Position vorgerückt ist, die er verwenden kann. Wie in der Abbildung gezeigt, sind start_lsn0-end_lsn0, start_lsn2-end_lsn2 und start_lsn3-end_lsn3 die neu angewendeten LSN-Intervalle von drei Benutzer-Threads. Das Intervall, das start_lsn1-end_lsn1 entspricht, wurde auf link_buf markiert. start_lsn3-end_lsn3 ist zu weit vom Ende entfernt und muss warten, bis link_buf fortschreitet, bevor es verwendet werden kann. 3. Markieren Sie nach dem Schreiben in den Protokollpuffer den Bereich von start_lsn->end_lsn bis link_buf (Hinweis: Da link_buf nur an der Position von start_lsn%capacity markiert ist, wird es nicht beeinflusst, selbst wenn end_lsn (m_tail, m_tail+m_capacity) überschreitet); 4. Wenn der Benutzer-Thread eine Transaktion festschreibt, wird das Ereignis log_sys.writer_event so gesetzt, dass der log_writer-Thread ausgelöst wird, um das Protokoll aus dem Redo-Log-Puffer in den Systemcache zu schreiben (der log_writer-Thread selbst fragt auch link_buf ab, um festzustellen, ob ein neues Protokoll geschrieben wurde). 5. Der log_writer-Thread treibt m_tail voran und schreibt den Protokollpuffer vor m_tail auf die Festplatte. Redo-Log-Speicherung und BenachrichtigungIm vorherigen Abschnitt wird kurz beschrieben, wie Redo-Protokolle übermittelt werden. Wenn Redo-Protokolle übermittelt und auf die Festplatte geschrieben werden, sind mehrere Threads beteiligt. Die Beziehung zwischen ihnen ist wie folgt: Wenn der Benutzer-Thread eine Lese-/Schreibtransaktion festschreibt, werden einige Redo-Protokolle generiert und im Redo-Protokollpuffer aufgezeichnet, während der MTR festgeschrieben wird. Der Benutzer-Thread versucht dann, writer_event festzulegen, um den log_writer-Thread zum Schreiben von Protokollen auszulösen, und lauscht auf sein eigenes flush_events[i]-Ereignis. Der Log_Writer-Thread führt Link_buf.m_tail weiter, schreibt das Redo-Protokoll vor der maximalen kontinuierlichen LSN in den Systemcache und setzt das Flusher_Event, um den Log_Flusher-Thread auszulösen. Der Thread log_flusher schreibt die in den Systemcache geschriebenen Protokolle auf die Festplatte und setzt flush_notifier_event, um den Thread log_flush_notifier auszulösen und den Benutzer zu benachrichtigen. log_flush_notifier berechnet das auszulösende Ereignis basierend auf der LSN der geleerten Festplatte und benachrichtigt den Benutzer-Thread. In der konkreten Implementierung werden mehrere Membervariablen in log_sys verwendet, um den Schreibstatus des Redo-Logs zu verfolgen. log_sys.recent_writtern.m_tail gibt den maximalen kontinuierlichen Bereich des Protokollpuffers an; log_sys.write_lsn gibt den Speicherort an, an dem die Daten in den Systemcache geschrieben werden; und log_sys.flushed_to_disk_lsn gibt den Speicherort an, an dem die Daten auf die Festplatte geschrieben wurden. Der Aufstiegsprozess der einzelnen Marken erfolgt wie folgt: Benutzer-Thread benachrichtigenWenn ein Benutzer eine Transaktion festschreibt, wird log_wait_for_write oder log_wait_for_flush entsprechend dem Parameter innodb_flush_log_at_trx_commit aufgerufen, um zu warten, bis das Redo-Protokoll in den Systemcache geschrieben oder auf die Festplatte geleert wurde. Die Benachrichtigung von Benutzer-Threads wird über das Ereignisarray log_sys.flush_events implementiert. Um zu vermeiden, dass zu viele Flush_events gleichzeitig benachrichtigt werden, werden Flush_events wie Buckets in verschiedene Benutzer-Threads aufgeteilt: Das Redo-Log wird in Logblöcke aufgeteilt. Angenommen, die Länge des Arrays log_sys.flush_events beträgt m, dann wird das Leeren des n-ten Logblocks durch das Ereignis flush_events[n%m] überwacht. Wenn der L1-te bis L2-te Protokollblock des Protokollpuffers auf die Festplatte geleert wird, werden die Flush_Events der Protokollblöcke zwischen L1 und L2 gesetzt, sodass die Benutzer-Threads des Redo-Protokolls zwischen L1 und L2 die Benachrichtigung erhalten. ZusammenfassenMySQL 8.0 behebt die Leistungseinbußen, die durch Sperrenwettbewerbe verursacht werden, wenn Benutzer-Threads Redo-Protokolle schreiben, indem Redo-Protokolle sperrenfrei gemacht werden. Gleichzeitig werden das Schreiben der Redo-Log-Datei und das Leeren des Redo-Logs vom Benutzer-Thread getrennt und in separate Threads extrahiert. Der Benutzer-Thread ist nur für das Schreiben des Redo-Logs in den Protokollpuffer verantwortlich und kümmert sich nicht mehr um die Details des Leerens des Redo-Logs auf die Festplatte. Er muss nur auf eine Benachrichtigung vom log_writer-Thread oder log_flusher-Thread warten. Oben finden Sie den detaillierten Inhalt der eingehenden Analyse des MySQL 8.0-Redo-Logs. Weitere Informationen zum MySQL 8.0-Redo-Log finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: Detaillierte Erklärung der CSS-Animationsattribut-Keyframes
>>: Lösung für mehrere Docker-Container, die nicht die gleiche Portnummer haben
In diesem Artikel wird der spezifische Code des W...
Das Implementierungsprinzip der bidirektionalen D...
Um Als ich kürzlich Vue lernte, schrieb ich ein k...
Methode join(): verbindet alle Elemente eines Arr...
/******************** * Anwendung von verknüpften...
In diesem Artikelbeispiel wird der spezifische Co...
Vorwort: Vue3 ist schon seit langem verfügbar. Vo...
Ich habe viele Tutorials gelesen, aber festgestel...
Manchmal müssen Sie Links verwenden, aber Sie müss...
Bei der tatsächlichen Verwendung ist es häufig er...
1. Um die MySQL-Datenbank herunterzuladen, besuch...
Erstellen einer Tabelle Tabelle erstellen Bestell...
Da sich die heimische Netzwerkumgebung immer weit...
DIV+CSS-Struktur Lernen Sie CSS-Layout? Sie beherr...
Vorwort Vor Feierabend erhielt der Autor eine Anf...