Heim  >  Artikel  >  Datenbank  >  Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

WBOY
WBOYnach vorne
2022-01-05 18:16:192172Durchsuche

Dieser Artikel vermittelt Ihnen Wissen über die erweiterte Architektur von MYSQL und der InnoDB-Speicher-Engine. Ich hoffe, er wird Ihnen hilfreich sein.

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

MySQL-Grundarchitekturdiagramm

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

Im Allgemeinen kann MySQL in zwei Teile unterteilt werden: die Serverschicht und die Speicher-Engine-Schicht.

Die Serverschicht umfasst Konnektoren, Abfrage-Caches, Analysatoren, Optimierer, Executoren usw. und deckt die meisten Kerndienstfunktionen von MySQL sowie alle integrierten Funktionen (wie Datum, Uhrzeit, Mathematik- und Verschlüsselungsfunktionen usw.) ab. ), alle übergreifenden Die Funktionen der Speicher-Engine werden in dieser Schicht implementiert, z. B. gespeicherte Prozeduren, Trigger, Ansichten usw.

Connector

Der Connector ist das, was Sie beim Herstellen einer Verbindung mit dem Client verwenden. Er ist dafür verantwortlich, eine Verbindung mit dem Client herzustellen, Berechtigungen einzuholen sowie die Verbindung aufrechtzuerhalten und zu verwalten.

Befehl: mysql -h$ip -P$port -u$user -p, drücken Sie die Eingabetaste und geben Sie das Passwort ein. Sie können das Passwort auch nach -p eingeben, es besteht jedoch die Gefahr eines Passwortlecks.

Prozessliste anzeigen, Sie können den Verbindungsstatus überprüfen. In der Befehlsspalte befindet sich ein Ruhezustand, der anzeigt, dass die Verbindung inaktiv ist.

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

Leere Verbindungen werden standardmäßig für 8 Stunden getrennt und können über den Parameter „wait_timeout“ konfiguriert werden.

In der Datenbank bedeutet eine lange Verbindung, dass nach erfolgreicher Verbindung immer dieselbe Verbindung verwendet wird, wenn der Client weiterhin Anfragen stellt. Eine kurze Verbindung bedeutet, dass die Verbindung nach einigen ausgeführten Abfragen getrennt wird und für die nächste Abfrage eine neue Verbindung hergestellt wird.

Da der Verbindungsaufbau Ressourcen verbraucht, wird empfohlen, möglichst lange Verbindungen zu verwenden. Nach der Verwendung langer Verbindungen erhöht sich jedoch der von MySQL belegte Speicher sehr schnell. Dies liegt daran, dass der von MySQL während der Ausführung vorübergehend verwendete Speicher verwaltet wird im Verbindungsobjekt. Diese Ressourcen werden freigegeben, wenn die Verbindung getrennt wird. Wenn sich daher lange Verbindungen ansammeln, belegen sie möglicherweise zu viel Speicher und werden vom System zwangsweise beendet (OOM). Dem Phänomen nach zu urteilen, startet MySQL abnormal neu.

Lösung:

Lange Verbindungen regelmäßig trennen. Nach längerer Verwendung oder nachdem das Programm festgestellt hat, dass eine große Abfrage ausgeführt wurde, die Speicher beansprucht, wird die Verbindung getrennt, und dann wird die Abfrage benötigt und dann erneut verbunden.

Wenn Sie MySQL 5.7 oder neuer verwenden, können Sie die Verbindungsressource neu initialisieren, indem Sie mysql_reset_connection jedes Mal ausführen, wenn Sie einen relativ großen Vorgang ausführen. Dieser Vorgang erfordert keine erneute Verbindung und keine Berechtigungsüberprüfung, sondern stellt die Verbindung in dem Zustand wieder her, in dem sie gerade erstellt wurde.

Abfrage-Cache

Der Abfrage-Cache speichert zuvor ausgeführte Anweisungen und ihre Ergebnisse im Speicher in Form von Schlüssel-Wert-Paaren. Der Schlüssel ist die Abfrageanweisung und der Wert ist das Abfrageergebnis. Wenn Ihre Abfrage den Schlüssel direkt in diesem Cache finden kann, wird der Wert direkt an den Client zurückgegeben.

Der Abfragecache wurde in MYSQL8 entfernt. Aufgrund häufiger Fehler im Abfragecache ist die Trefferquote niedrig.

Analysator

Der Analysator führt zunächst eine „lexikalische Analyse“ durch, um zu identifizieren, was die darin enthaltenen Zeichenfolgen sind und was sie darstellen. Anschließend müssen Sie eine „Syntaxanalyse“ durchführen, um festzustellen, ob die von Ihnen eingegebene SQL-Anweisung der MySQL-Syntax entspricht.

Optimizer

Executor

Die Storage-Engine-Schicht ist für die Speicherung und den Abruf von Daten verantwortlich. Sein Architekturmodell ist Plug-in und unterstützt mehrere Speicher-Engines wie InnoDB, MyISAM und Memory. Die derzeit am häufigsten verwendete Speicher-Engine ist InnoDB, die seit MySQL 5.5.5 zur Standard-Speicher-Engine geworden ist.

Ein Select-Anweisungsausführungsprozess

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

Die obige Abbildung zeigt als Beispiel die InnoDB-Speicher-Engine:

  • Der Benutzer sendet eine Anfrage an Tomcat und stellt die Verbindung her wird über den Tomcat-Link-Pool und den MySQL-Verbindungspool hergestellt. Senden Sie dann die SQL-Anweisung über die Verbindung

  • MySQL verfügt über einen separaten Überwachungsthread, liest die Anforderungsdaten und ruft die in der Verbindung angeforderte SQL-Anweisung ab

  • Senden Sie die erhaltenen SQL-Daten an die SQL-Schnittstelle. Ausführung;

  • SQL-Schnittstelle sendet SQL zum Parsen;

  • Sendet das analysierte SQL an den Abfrageoptimierer, findet den optimalen Abfragepfad und sendet ihn dann an den Executor;

  • Der Executor ruft die Schnittstelle der Speicher-Engine gemäß dem optimierten Ausführungsplan auf und führt sie in einer bestimmten Reihenfolge und in bestimmten Schritten aus.

  • Zum Beispiel kann der Ausführende zunächst eine Schnittstelle der Speicher-Engine aufrufen, um die erste Datenzeile in der Tabelle „Benutzer“ abzurufen, und dann feststellen, ob der Wert des Felds „ID“ dieser Daten gleich ist Wir erwarten einen Wert. Wenn nicht, rufen Sie weiterhin die Speicher-Engine-Schnittstelle auf, um die nächste Datenzeile in der Tabelle „Benutzer“ abzurufen. Basierend auf der obigen Idee verwendet der Executor eine Reihe von Ausführungsplänen, die von unserem Optimierer generiert wurden, und ruft dann kontinuierlich verschiedene Schnittstellen der Speicher-Engine auf, um den Ausführungsplan der SQL-Anweisung zu vervollständigen, der grob gesagt darin besteht, einige davon kontinuierlich zu aktualisieren oder zu extrahieren Daten kommen heraus.

Hier geht es um mehrere Fragen:

Was genau ist der MySQL-Treiber?

Nehmen Sie Java als Beispiel. Wenn wir auf eine MySQL-Datenbank im Java-System zugreifen möchten, müssen wir in Maven beispielsweise einen MySQL-Treiber hinzufügen MySQL-Treiber? Tatsächlich stellt der L-Treiber eine Netzwerkverbindung mit der Datenbank auf der untersten Ebene her und kann dann eine Anfrage an den Datenbankserver senden. Lassen Sie das in der Sprache geschriebene System über den MySQL-Treiber auf die Datenbank zugreifen, wie unten gezeigt

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-EngineWofür wird der Datenbankverbindungspool verwendet?

Angenommen, ein Webdienst wird in Java entwickelt und auf Tomcat bereitgestellt. Tomcat kann Anforderungen gleichzeitig mit mehreren Threads verarbeiten. Daher ist es erstens unmöglich, nur eine Datenbankverbindung herzustellen (mehrere Anforderungen, um eine Verbindung abzurufen). ineffizient).

Zweitens, was ist, wenn für jede Anfrage eine Datenbankverbindung erstellt wird, da es sehr zeitaufwändig ist, jedes Mal eine Verbindung herzustellen und die SQL-Anweisung auszuführen? und das anschließende Löschen der Datenbank führt zu Leistungsproblemen und häufigem Erstellen und Vernichten.

Verwenden Sie daher im Allgemeinen einen Datenbankverbindungspool, dh verwalten Sie mehrere Datenbankverbindungen in einem Pool, lassen Sie mehrere Threads unterschiedliche Datenbankverbindungen darin verwenden, um SQL-Anweisungen auszuführen, und zerstören Sie dann nach der Ausführung der SQL-Anweisung die Datenbankverbindung nicht. Stattdessen wird die Verbindung wieder in den Pool gelegt und kann später wieder verwendet werden. Basierend auf einem solchen Datenbankverbindungspoolmechanismus kann das Problem gelöst werden, dass mehrere Threads gleichzeitig mehrere Datenbankverbindungen zum Ausführen von SQL-Anweisungen verwenden, und das Problem der Zerstörung von Datenbankverbindungen nach der Verwendung kann ebenfalls vermieden werden.

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-EngineWofür wird der Verbindungspool der MySQL-Datenbank verwendet?

Der Verbindungspool der MySQL-Datenbank hat dieselbe Funktion wie der Verbindungspool der Java-Anwendung, und beide spielen die Rolle der Wiederverwendung von Verbindungen.

InnoDB-Speicher-Engine

Kurzanalyse der InnoDB-Architektur

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-EngineWie aus dem Bild ersichtlich ist, besteht die InnoDB-Speicher-Engine aus drei Teilen: Speicherpool, Hintergrundthread und Festplattendatei

Andere Eines, um die wichtigsten Punkte hervorzuheben. Bild:

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

InnoDB-Speicher-Engine Teil Eins: Speicherstruktur

Pufferpool

InnoDB-Speicher-Engine basiert auf Festplattenspeicher und verwaltet die Datensätze in Seiten Aufgrund der Kluft zwischen CPU-Geschwindigkeit und Festplattengeschwindigkeit verwenden festplattenbasierte Datenbanksysteme häufig Pufferpooldatensätze, um die Gesamtleistung der Datenbank zu verbessern.

Beim Ausführen eines Lesevorgangs in der Datenbank wird die von der Festplatte gelesene Seite im Pufferpool abgelegt. Wenn dieselbe Seite das nächste Mal gelesen wird, stellen Sie zunächst fest, ob sich die Seite im Pufferpool befindet. Wenn es sich im Pufferpool befindet, heißt es, dass die Seite im Pufferpool gefunden wird und die Seite direkt gelesen wird. Andernfalls wird die Seite auf der Festplatte gelesen.

Für den Änderungsvorgang von Seiten in der Datenbank wird zunächst die Seite im Pufferpool geändert und dann mit einer bestimmten Häufigkeit auf der Festplatte aktualisiert. Der Vorgang zum Aktualisieren der Seite vom Pufferpool zurück auf die Festplatte wird nicht ausgelöst Jedes Mal, wenn die Seite aktualisiert wird, wird sie über einen Mechanismus namens CheckPoint zurück auf die Festplatte geleert. Daher wirkt sich die Größe des Pufferpools direkt auf die Gesamtleistung der Datenbank aus. Sie kann über den Konfigurationsparameter innodb_buffer_pool_size festgelegt werden, was immer noch etwas klein ist, wenn es sich bei Ihrer Datenbank um eine 16-Kern-Datenbank handelt Maschine, dann können Sie dem Pufferpool 2 GB Speicher zuweisen.

Da der Pufferpool nicht unendlich ist, da die Datenseiten auf der Festplatte kontinuierlich in den Pufferpool geladen werden, ist der Pufferpool immer aufgebraucht. Zu diesem Zeitpunkt können nur einige Cache-Seiten entfernt werden Insbesondere führt der neueste LRU-Algorithmus (LRU) eine neue LRU-verknüpfte Liste ein. Mithilfe dieser LRU-verknüpften Liste können Sie feststellen, welche Cache-Seiten am wenigsten verwendet wurden. Wenn Sie dann eine Cache-Seite freigeben müssen auf die Festplatte. Zu diesem Zeitpunkt können Sie die zuletzt verwendete Cache-Seite in der LRU-Liste auswählen, die gelöscht werden soll.

Zu den im Pufferpool zwischengespeicherten Datenseitentypen gehören: Indexseiten, Datenseiten, Rückgängig-Seiten, Einfügungspuffer, adaptive Hash-Indizes, Sperrinformationen und Datenwörterbuchinformationen, die in InnoDB gespeichert sind.

Datenseite und Indexseite

Seite (Seite) ist die grundlegendste Struktur des Innodb-Speichers und die kleinste Einheit der Innodb-Festplattenverwaltung. Alle mit der Datenbank verbundenen Inhalte werden in der Seitenstruktur gespeichert. Seiten werden in verschiedene Typen unterteilt, wobei Datenseiten und Indexseiten die beiden wichtigsten Typen sind.

Puffer einfügen

Beim Ausführen von Einfügevorgängen auf der InnoDB-Engine ist es im Allgemeinen erforderlich, in der Reihenfolge des Primärschlüssels einzufügen, um eine höhere Einfügeleistung zu erzielen. Wenn eine Tabelle einen nicht gruppierten, nicht eindeutigen Index enthält, werden die Datenseiten beim Einfügen weiterhin in der Reihenfolge des Primärschlüssels gespeichert, das Einfügen von nicht gruppierten Indexblattknoten erfolgt jedoch nicht mehr sequentiell , Es ist notwendig, dass der diskrete Zugriff auf nicht gruppierte Indexseiten aufgrund des Vorhandenseins zufälliger Lesevorgänge zu einer Leistungseinbuße bei Einfügevorgängen führt.

So war die InnoDB-Speicher-Engine Vorreiter beim Design des Einfügepuffers. Bei Einfüge- oder Aktualisierungsvorgängen für nicht gruppierte Indizes wird nicht jedes Mal direkt in die Indexseite eingefügt, sondern zunächst ermittelt, ob sich die eingefügte nicht gruppierte Indexseite im Puffer befindet Wenn es vorhanden ist, wird es direkt eingefügt. Wenn es nicht vorhanden ist, wird es zuerst in ein Insert Buffer-Objekt eingefügt, was wie Betrug aussieht. Der nicht gruppierte Index der Datenbank wurde in den Blattknoten eingefügt, ist aber nicht vorhanden. Er wird lediglich an einem anderen Ort gespeichert. Führen Sie dann den Zusammenführungsvorgang des Einfügepuffers und der Unterknoten der Hilfsindexseite in einer bestimmten Häufigkeit und Situation aus. Zu diesem Zeitpunkt können normalerweise mehrere Einfügungen zu einem Vorgang zusammengeführt werden (da sie sich auf einer Indexseite befinden). Verbessert die Leistung bei nicht gruppierten Indexeinfügungen erheblich.

Die Verwendung von Insert Buffer muss jedoch gleichzeitig die folgenden zwei Bedingungen erfüllen:

  • Der Index ist ein Sekundärindex (Sekundärindex);

  • Der Index ist nicht eindeutig (eindeutig).

Wenn die beiden oben genannten Bedingungen erfüllt sind, verwendet die InnoDB-Speicher-Engine den Einfügepuffer, was die Leistung von Einfügevorgängen verbessern kann. Stellen Sie sich jedoch eine Situation vor, in der die Anwendung eine große Anzahl von Einfügevorgängen ausführt, die alle nicht eindeutige, nicht gruppierte Indizes beinhalten, d. h. die Verwendung von Einfügepuffer. Wenn die MySQL-Datenbank zu diesem Zeitpunkt ausfällt, gibt es eine große Anzahl von Einfügepuffern, die nicht in den eigentlichen nicht gruppierten Index eingebunden werden.

Daher kann die Genesung zu diesem Zeitpunkt lange dauern, im Extremfall sogar mehrere Stunden. Der Hilfsindex kann nicht eindeutig sein, da die Datenbank beim Einfügen des Puffers nicht die Indexseite nachschlägt, um die Eindeutigkeit des eingefügten Datensatzes zu ermitteln. Wenn Sie suchen, kommt es definitiv zu einem diskreten Lesen, wodurch der Insert Buffer seine Bedeutung verliert.

Sie können die Einfügungspufferinformationen über den Befehl SHOW ENGINE INNODB STATUS anzeigen. Die Seg-Größe zeigt an, dass die aktuelle Einfügungspuffergröße 11336 × 16 KB beträgt, was etwa 177 MB entspricht Liste; Größe stellt die Anzahl der zusammengeführten Datensatzseiten dar. Die zweite fettgedruckte Zeile ist möglicherweise das, was den Benutzern wirklich am Herzen liegt, da sie die Verbesserung der Einfügeleistung zeigt. „Inserts“ stellt die Anzahl der eingefügten Datensätze dar; „merged recs“ stellt die Anzahl der zusammengeführten eingefügten Datensätze dar; „merges“ stellt die Anzahl der Zusammenführungen dar, also die Anzahl der tatsächlichen Seitenlesevorgänge. merges: merged recs beträgt etwa 1:3, was bedeutet, dass der Einfügepuffer die diskreten logischen E/A-Anforderungen für nicht gruppierte Indexseiten um etwa 2/3 reduziert.

Wie bereits erwähnt, gibt es derzeit ein Problem mit dem Einfügepuffer: Bei intensivem Schreiben belegt der Einfügepuffer zu viel Pufferpoolspeicher (standardmäßig kann er bis zu 1/2 davon belegen). Der Pufferpool. Das Folgende ist der Initialisierungsvorgang für den Einfügepuffer im Quellcode der InnoDB-Speicher-Engine: Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

Change Buffer

Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

InnoDB hat Change Buffer seit Version 1.0.x eingeführt, was als aktualisierte Version von Insert Buffer angesehen werden kann , InnodB Die Speicher-Engine kann DML-Vorgänge puffern – INSERT, DELETE und UPDATE. Dies sind: Puffer einfügen, Puffer löschen und Puffer löschen. Natürlich sind die anwendbaren Objekte von Puffer ändern immer noch nicht eindeutig Hilfsindizes.

Der UPDATE-Vorgang für einen Datensatz kann in zwei Prozesse unterteilt werden:

Markieren des Datensatzes als gelöscht;

  • Löschen des Datensatzes

  • Damit wird der Datensatz zum Löschen markiert. PurgeBuffer entspricht dem zweiten Prozess der UPDATE-Operation, bei dem der eigentliche Löschvorgang aufgezeichnet wird. Gleichzeitig stellt die InnoDB-Speicher-Engine den Parameter innodb_change_buffering bereit, der zum Aktivieren verschiedener Pufferoptionen verwendet wird. Die optionalen Werte dieses Parameters sind: Einfügungen, Löschungen, Löschungen, Änderungen, alle, keine. Einfügungen, Löschungen und Löschungen sind die drei zuvor besprochenen Situationen. „Änderungen“ bedeutet, dass Einfügungen und Löschungen aktiviert sind, „alle“ bedeutet, dass alle aktiviert sind, und „keine“ bedeutet, dass keines aktiviert ist. Der Standardwert dieses Parameters ist all.

    从 InnoDB1.2.x版本开始,可以通过参数 innodb_change_buffer_max_size 来控制Change Buffer最大使用内存的数量:

    mysql> show variables like 'innodb_change_buffer_max_size';
    +-------------------------------+-------+
    | Variable_name                 | Value |
    +-------------------------------+-------+
    | innodb_change_buffer_max_size | 25    |
    +-------------------------------+-------+
    1 row in set (0.05 sec)

    innodb_change_buffer_max_size 值默认为25,表示最多使用1/4的缓冲池内存空间。

    而需要注意的是,该参数的最大有效值为50在 MySQL5.5版本中通过命令 SHOW ENGINE INNODB STATUS,可以观察到类似如下的内容:

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    可以看到这里显示了 merged operations和 discarded operation,并且下面具体显示 Change Buffer中每个操作的次数。 Insert 表示 Insert Buffer; delete mark表示 Delete Buffer; delete表示 Purge Buffer; discarded operations表示当 Change Buffer发生 merge时,表已经被删除,此时就无需再将记录合并(merge)到辅助索引中了。

    自适应哈希索引

    InnoDB 会根据访问的频率和模式,为热点页建立哈希索引,来提高查询效率。InnoDB 存储引擎会监控对表上各个索引页的查询,如果观察到建立哈希索引可以带来速度上的提升,则建立哈希索引,所以叫做自适应哈希索引。

    自适应哈希索引通过缓冲池的B+树页构建而来,因此建立速度很快,而且不需要对整张数据表建立哈希索引。其有一个要求,即对这个页的连续访问模式必须一样的,也就是说其查询的条件必须完全一样,而且必须是连续的。

    锁信息(lock info)

    我们都知道,InnoDB 存储引擎会在行级别上对表数据进行上锁,不过 InnoDB 打开一张表,就增加一个对应的对象到数据字典。

    数据字典

    对数据库中的数据、库对象、表对象等的元信息的集合。在 MySQL 中,数据字典信息内容就包括表结构、数据库名或表名、字段的数据类型、视图、索引、表字段信息、存储过程、触发器等内容,MySQL INFORMATION_SCHEMA 库提供了对数据局元数据、统计信息、以及有关MySQL Server的访问信息(例如:数据库名或表名,字段的数据类型和访问权限等)。该库中保存的信息也可以称为MySQL的数据字典。

    预读机制

    MySQL的预读机制,就是当你从磁盘上加载一个数据页的时候,他可能会连带着把这个数据页相邻的其他数据页,也加载到缓存里去!

    举个例子,假设现在有两个空闲缓存页,然后在加载一个数据页的时候,连带着把他的一个相邻的数据页也加载到缓存里去了,正好每个数据页放入一个空闲缓存页!

    哪些情况下会触发MySQL的预读机制?

    • 有一个参数是innodb_read_ahead_threshold,他的默认值是56,意思就是如果顺序的访问了一个区里的多个数据页,访问的数据页的数量超过了这个阈值,此时就会触发预读机制,把下一个相邻区中的所有数据页都加载到缓存里去。

    • 如果Buffer Pool里缓存了一个区里的13个连续的数据页,而且这些数据页都是比较频繁会被访问的,此时就会直接触发预读机制,把这个区里的其他的数据页都加载到缓存里去这个机制是通过参数innodb_random_read_ahead来控制的,他默认是OFF,也就是这个规则是关闭的。

    所以默认情况下,主要是第一个规则可能会触发预读机制,一下子把很多相邻区里的数据页加载到缓存里去。

    预读机制的好处为了提升性能。假设你读取了数据页01到缓存页里去,那么接下来有可能会接着顺序读取数据页01相邻的数据页02到缓存页里去,这个时候,是不是可能在读取数据页02的时候要再次发起一次磁盘IO?

    所以为了优化性能,MySQL才设计了预读机制,也就是说如果在一个区内,你顺序读取了好多数据页了,比如数据页01到数据页56都被你依次顺序读取了,MySQL会判断,你可能接着会继续顺序读取后面的数据页。那么此时就提前把后续的一大堆数据页(比如数据页57到数据页72)都读取到Buffer Pool里去。

    缓冲池内存管理

    这里需要了解三个链表(Free List、Flush List、LRU List),

    • Die Datenseiten und Cache-Seiten auf der Free List-Festplatte stehen in einer Eins-zu-eins-Entsprechung, beide sind 16 KB groß und eine Datenseite entspricht einer Cache-Seite. Die Datenbank entwirft eine freie verknüpfte Liste für den Pufferpool, bei der es sich um eine bidirektionale verknüpfte Listendatenstruktur handelt. In dieser freien verknüpften Liste ist jeder Knoten die Adresse einer freien Cache-Seite, die den Datenblock beschreibt Solange eine Cache-Seite frei ist, wird sein Beschreibungsdatenblock in diese freie verknüpfte Liste aufgenommen. Beim ersten Start der Datenbank sind möglicherweise alle Cache-Seiten frei, da es sich möglicherweise um eine leere Datenbank ohne Daten handelt. Daher werden zu diesem Zeitpunkt die Beschreibungsdatenblöcke aller Cache-Seiten in diese freie verknüpfte Liste eingefügt Diese freie verknüpfte Liste verfügt über einen Basisknoten, der sich auf den Kopfknoten und den Endknoten der verknüpften Liste bezieht. Außerdem wird gespeichert, wie viele Knoten, die Datenblöcke beschreiben, in der verknüpften Liste vorhanden sind, dh wie viele freie Cache-Seiten vorhanden sind . .

    • Flush List ähnelt der verknüpften Liste Free List. Das Wesentliche der Flush-verknüpften Liste besteht darin, zwei Zeiger im Beschreibungsdatenblock der Cache-Seite zu verwenden, um mithilfe des modifizierten Beschreibungsdatenblocks eine bidirektionale verknüpfte Liste zu bilden die Cache-Seite. Der Beschreibungsdatenblock jeder geänderten Cache-Seite wird zur leeren verknüpften Liste hinzugefügt. Flush bedeutet, dass es sich um schmutzige Seiten handelt, die in Zukunft auf die Festplatte geleert werden.

    • LRU-Liste Da die Größe des Pufferpools sicher ist, sind die Daten der freien Cache-Seite in der freien verknüpften Liste sicher, wenn Sie die Datenseiten auf der Festplatte weiterhin in die freie Cache-Seite laden. Kostenlose kostenlose Cache-Seiten werden ständig aus der verknüpften Liste entfernt. Früher oder später wird es einen Moment geben, in dem es keine kostenlosen Cache-Seiten mehr gibt. Zu diesem Zeitpunkt müssen einige Cache-Seiten entfernt werden beseitigt? Dies erfordert die Verwendung der Cache-Trefferrate. Diejenigen mit den meisten Cache-Treffer werden häufig verwendet, und diejenigen, die nicht häufig verwendet werden, können eliminiert werden. Daher wird die LRU-verknüpfte Liste eingeführt, um zu bestimmen, welche Cache-Seiten nicht häufig verwendet werden.

    Was ist also die Eliminierungsstrategie der LRU-verknüpften Liste?

    Angenommen, wenn wir eine Datenseite von der Festplatte auf die Cache-Seite laden, fügen wir den Beschreibungsdatenblock dieser Cache-Seite in den Kopf der verknüpften LRU-Liste ein. Solange es eine Cache-Seite mit Daten gibt, wird dies der Fall sein in der LRU sein, und vor kurzem Die Cache-Seite der geladenen Daten wird an den Anfang der LRU-verknüpften Liste gestellt und dann wird eine bestimmte Cache-Seite zum Ende hinzugefügt Solange eine Abfrage auftritt, wird sie verschoben zum Kopf, und dann muss der Schwanz entfernt werden.

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Aber ist das wirklich in Ordnung?

    Im ersten Fall wird der Read-Ahead-Mechanismus zerstört.

    Da der Read-Ahead-Mechanismus benachbarte Datenseiten, auf die nicht zugegriffen wurde, in den Cache lädt, wird tatsächlich nur auf eine Cache-Seite zugegriffen, und auf die andere Der Zugriff erfolgt über den Read-Ahead-Mechanismus. Tatsächlich hat niemand auf die geladene Cache-Seite zugegriffen. Zu diesem Zeitpunkt befinden sich beide Cache-Seiten vor der LRU-verknüpften Liste Wenn keine freien Cache-Seiten vorhanden sind, muss zu diesem Zeitpunkt eine neue geladen werden. Wenn eine Datenseite vorhanden ist, müssen wir die sogenannte „zuletzt verwendete Cache-Seite“ vom Ende der LRU-verknüpften Liste entfernen , leeren Sie es auf die Festplatte und geben Sie dann eine freie Cache-Seite frei. Das ist offensichtlich sehr unvernünftig.

    Die zweite Situation kann dazu führen, dass häufig aufgerufene Cache-Seiten entfernt werden. Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Der vollständige Tabellenscan führt dazu, dass er alle Datenseiten in der Tabelle auf einmal direkt von der Festplatte in den Pufferpool lädt. Zu diesem Zeitpunkt können alle Datenseiten dieser Tabelle einzeln in jede Cache-Seite geladen werden! Zu diesem Zeitpunkt ist es möglich, dass eine große Liste von Cache-Seiten am Anfang der LRU-verknüpften Liste alle Cache-Seiten sind, die durch einen vollständigen Tabellenscan geladen wurden! Was passiert also, wenn nach diesem vollständigen Tabellenscan die Daten in dieser Tabelle in Zukunft kaum noch verwendet werden? Zu diesem Zeitpunkt handelt es sich am Ende der LRU-verknüpften Liste möglicherweise um zwischengespeicherte Seiten, auf die zuvor häufig zugegriffen wurde! Wenn Sie dann einige Cache-Seiten entfernen möchten, um Platz zu schaffen, entfernen Sie die Cache-Seiten, auf die häufig zugegriffen wurde, am Ende der LRU-Liste, sodass eine große Anzahl selten aufgerufener Seiten übrig bleibt, die beim vorherigen vollständigen Tabellenscan geladen wurden. Gecachte Seite!

    Optimieren Sie den LRU-Algorithmus: Entwerfen Sie die LRU-verknüpfte Liste basierend auf der Idee der Trennung heißer und kalter Daten.

    Wenn MySQL die verknüpfte LRU-Liste entwirft, übernimmt es tatsächlich die Idee der Trennung heißer und kalter Daten . Die verknüpfte LRU-Liste wird in zwei Teile aufgeteilt: Der eine besteht aus heißen Daten und der andere aus kalten Daten. Das Verhältnis von heißen und kalten Daten wird durch den Parameter innodb_old_blocks_pct gesteuert. Sein Standardwert ist 37, was bedeutet, dass kalte Daten 37 ausmachen %. Wenn die Datenseite zum ersten Mal in den Cache geladen wird, wird die Cache-Seite tatsächlich an der Spitze der verknüpften Liste im kalten Datenbereich platziert.

    Dann hat MySQL eine Regel festgelegt. Der Standardwert ist 1000, was 1000 Millisekunden entspricht. Nachdem eine Datenseite in die Cache-Seite geladen wurde, wird sie aufgerufen an den Kopf der verknüpften Liste im Hot-Data-Bereich verschoben werden. Angenommen, Sie laden eine Datenseite in den Cache und greifen dann nach 1 Sekunde auf diese Cache-Seite zu, was bedeutet, dass Sie in Zukunft wahrscheinlich häufig darauf zugreifen werden. Das Zeitlimit beträgt 1 Sekunde, sodass Sie erst nach 1 Sekunde auf diese zwischengespeicherte Seite zugreifen . Cachen Sie die Seite und er platziert die Cache-Seite für Sie an der Spitze der verknüpften Liste im Hot-Data-Bereich.

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    In diesem Fall befinden sich die Daten für das Vorlesen und den vollständigen Tabellenscan nur im Kaltdaten-Header und gelangen nicht von Anfang an in den Hot-Datenbereich.

    LRU-Algorithmus ist extrem optimiert

    Die Zugriffsregeln des Hot-Data-Bereichs der LRU-verknüpften Liste sind optimiert, dh nur, wenn auf die Cache-Seiten in den letzten drei Vierteln des Hot-Data-Bereichs zugegriffen wird , Sie werden an die Spitze der verknüpften Liste verschoben. Wenn auf das erste Viertel der Cache-Seiten im Hot-Data-Bereich zugegriffen wird, werden diese nicht an den Kopf der verknüpften Liste verschoben.

    Angenommen, die verknüpfte Liste des Hot-Data-Bereichs enthält beispielsweise 100 Cache-Seiten, dann werden die obersten 25 Cache-Seiten nicht an den Anfang der verknüpften Liste verschoben, selbst wenn auf sie zugegriffen wird. Aber für die nächsten 75 Cache-Seiten werden sie, solange auf sie zugegriffen wird, an die Spitze der verknüpften Liste verschoben. Auf diese Weise kann er die Bewegung von Knoten in der verknüpften Liste so weit wie möglich reduzieren.

    Timing der Löschung von Cache-Seiten durch LRU-verknüpfte Listen

    Wenn MySQL CRUD ausführt, betreibt es zunächst eine große Anzahl von Cache-Seiten und mehrere entsprechende verknüpfte Listen. Wenn die Cache-Seiten dann voll sind, müssen Sie einen Weg finden, einige Cache-Seiten auf die Festplatte zu leeren, diese Cache-Seiten dann zu löschen und dann die erforderlichen Datenseiten in die Cache-Seiten zu laden!

    Wir wissen bereits, dass er Cache-Seiten basierend auf der LRU-verknüpften Liste eliminiert. Wann hat er also die Cache-Seiten im kalten Datenbereich der LRU-verknüpften Liste auf die Festplatte geleert? Tatsächlich hat er die folgenden drei Möglichkeiten:

    Regelmäßig einige Cache-Seiten am Ende der LRU auf die Festplatte leeren.

    • Der Hintergrundthread führt eine geplante Aufgabe aus. Diese geplante Aufgabe wird den kalten Datenbereich leeren Von Zeit zu Zeit die LRU-verknüpfte Liste leeren, einige Cache-Seiten am Ende der Seite auf die Festplatte leeren, diese Cache-Seiten löschen und sie wieder zur freien verknüpften Liste hinzufügen.

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Leeren Sie regelmäßig einige Cache-Seiten in der leeren verknüpften Liste auf die Festplatte.

    Wenn Sie nur die Cache-Seiten im kalten Datenbereich der verknüpften LRU-Liste auf die Festplatte leeren, reicht dies nicht aus. Da sich im Hot-Data-Bereich der verknüpften Liste viele Cache-Seiten befinden, werden sie möglicherweise auch häufig geändert. Werden sie niemals auf die Festplatte geleert?

    Dieser Hintergrundthread schreibt also auch alle Cache-Seiten in der Flush-Link-Liste auf die Festplatte, wenn MySQL nicht sehr ausgelastet ist. Auf diese Weise werden die von Ihnen geänderten Daten früher oder später auf die Festplatte geleert!

    Solange eine Welle von Cache-Seiten in der Flush-Link-Liste auf die Festplatte geleert wird, werden diese Cache-Seiten auch aus der Flush-Link-Liste und der LRU-Link-Liste entfernt und dann der freien Link-Liste hinzugefügt!

    Der Gesamteffekt besteht also darin, kontinuierlich Daten in die Cache-Seite zu laden, die Cache-Daten ständig abzufragen und zu ändern, und dann nimmt die Cache-Seite in der freien verknüpften Liste weiter ab und die Cache-Seite in der leeren verknüpften Liste nimmt weiter zu . Die Cache-Seiten in der lru-verknüpften Liste nehmen ständig zu und verschieben sich.

    Auf der anderen Seite leert Ihr Hintergrundthread ständig die Cache-Seiten des kalten Datenbereichs der lru-verknüpften Liste und die Cache-Seiten der leeren verknüpften Liste auf die Festplatte, um die Cache-Seiten zu löschen, und leert sie dann Die Anzahl der Cache-Seiten in der verknüpften Liste und der LRU-Liste nimmt ab, während die Anzahl der Cache-Seiten in der freien Liste zunimmt.

    Die kostenlose verknüpfte Liste hat keine freien Cache-Seiten

    Wenn alle kostenlosen verknüpften Listen verwendet werden und Sie zu diesem Zeitpunkt die Datenseite von der Festplatte in eine freie Cache-Seite laden möchten, wird sie von geladen Kalter Datenbereich der LRU-verknüpften Liste. Wenn am Ende eine Cache-Seite gefunden wird, muss es sich um die am seltensten verwendete Cache-Seite handeln! Spülen Sie es dann auf die Festplatte, löschen Sie es und laden Sie dann die Datenseite in die freie Cache-Seite!

    Um die Verwendung der drei verknüpften Listen zusammenzufassen: Wenn der Pufferpool verwendet wird, lädt er tatsächlich häufig Datenseiten von der Festplatte in seine Cache-Seiten, und dann werden die frei verknüpften Listen, die verknüpften Flush-Listen und die verknüpften LRU-Listen geladen Alle werden gleichzeitig geladen. Wenn beispielsweise Daten in eine Cache-Seite geladen werden, wird die Cache-Seite aus der freien verknüpften Liste entfernt und dann wird der Kopf des kalten Datenbereichs der lru-verknüpften Liste entfernt in der Cache-Seite platziert.

    Wenn Sie dann eine Cache-Seite ändern, wird die schmutzige Seite in der Flush-Link-Liste aufgezeichnet, und die LRU-Link-Liste bewegt Sie möglicherweise auch vom Kaltdatenbereich zum Kopf des Hot-Datenbereichs.

    Wenn Sie eine Cache-Seite abfragen, wird die Cache-Seite in den Hot-Data-Bereich in der verknüpften LRU-Liste verschoben, oder sie wird möglicherweise an den Kopf im Hot-Data-Bereich verschoben.

    Redo-Log-Puffer Redo-Log-Puffer

    InnoDB verfügt über einen Pufferpool (kurz bp). bp ist der Cache von Datenbankseiten, der zuerst auf der Seite von bp ausgeführt wird. Anschließend werden diese Seiten als schmutzig (dirty page) markiert und anschließend in den Master-Thread oder A eingefügt Ein dedizierter Reinigungsthread schreibt diese Seiten regelmäßig auf die Festplatte (Festplatte oder SSD).

    Der Vorteil besteht darin, dass die Festplatte nicht für jeden Schreibvorgang betätigt werden muss, was zu einer großen Menge an zufälligen E/A-Vorgängen führt. Durch das regelmäßige Bürsten können mehrere Änderungen an der Seite in einem E/A-Vorgang zusammengeführt werden Zugriffsverzögerung. Wenn der Server jedoch abnormal heruntergefahren wird, bevor die fehlerhafte Seite auf die Festplatte geleert wird, gehen diese Änderungsvorgänge verloren. Wenn der Schreibvorgang ausgeführt wird, kann die Datenbank aufgrund beschädigter Datendateien sogar nicht mehr verfügbar sein.

    Um die oben genannten Probleme zu vermeiden, schreibt Innodb alle Änderungsvorgänge an der Seite in eine spezielle Datei und führt Wiederherstellungsvorgänge aus dieser Datei aus, wenn die Datenbank gestartet wird. Diese Datei ist die Redo-Log-Datei. Diese Technologie verzögert die Aktualisierung von BP-Seiten, wodurch der Datenbankdurchsatz verbessert und die Zugriffslatenz effektiv reduziert wird.

    Das Problem ist der zusätzliche Aufwand beim Schreiben von Redo-Log-Vorgängen (sequentielle E/A, natürlich schnell) und die Zeit, die erforderlich ist, um den Vorgang beim Start der Datenbank fortzusetzen.

    Das Redo-Log besteht aus zwei Teilen: dem Redo-Log-Puffer und der Redo-Log-Datei (im Abschnitt „Festplattendatei“ vorgestellt). Innodb ist eine Speicher-Engine, die Transaktionen unterstützt. Wenn eine Transaktion festgeschrieben wird, müssen zunächst alle Protokolle der Transaktion in die Redo-Log-Datei geschrieben werden. Der gesamte Transaktionsvorgang ist erst abgeschlossen, wenn der Festschreibungsvorgang der Transaktion abgeschlossen ist. Jedes Mal, wenn der Redo-Log-Puffer in die Redo-Log-Datei geschrieben wird, muss eine fsync-Operation aufgerufen werden, da der Redo-Log-Puffer den Inhalt nur zuerst in das Puffersystem des Betriebssystems schreibt und nicht sicherstellt, dass er direkt geschrieben wird Auf die Festplatte muss ein fsync-Vorgang ausgeführt werden. Daher bestimmt die Leistung der Festplatte in gewissem Maße auch die Leistung der Transaktionsübermittlung (der Redo-Log-Disk-Drop-Mechanismus wird später eingeführt).

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Die InnoDB-Speicher-Engine legt die Redo-Log-Informationen zunächst in den Redo-Log-Puffer und leert sie dann mit einer bestimmten Häufigkeit in die Redo-Log-Datei. Der Redo-Log-Puffer muss im Allgemeinen nicht sehr groß eingestellt werden. Da der Redo-Log-Puffer im Allgemeinen jede Sekunde in die Protokolldatei geleert wird, kann er über den Konfigurationsparameter Innodb_log_buffer_size gesteuert werden, der standardmäßig 8 MB beträgt.

    Double Write

    Wenn Insert Buffer eine Leistungsverbesserung für die InnoDB-Speicher-Engine bringt, dann bringt Double Wtite die Zuverlässigkeit der Datenseite für die InnoDB-Speicher-Engine.

    Die Seitengröße von InnoDB beträgt im Allgemeinen 16 KB, und die Datenüberprüfung wird ebenfalls auf der Grundlage dieser 16 KB berechnet. Das Schreiben von Daten auf die Festplatte erfolgt in Seiteneinheiten. Da das Dateisystem in den meisten Fällen für große Datenseiten (z. B. 16 KB von InnoDB) nicht atomar ist, wissen wir, dass bei einem Serverausfall möglicherweise nur ein Teil des Schreibvorgangs ausgeführt werden kann. Als 16 KB Daten auf 4 KB geschrieben wurden, kam es zu einem Systemstromausfall und einem Betriebssystemabsturz. Nur ein Teil des Schreibvorgangs war erfolgreich. In diesem Fall handelte es sich um ein teilweises Seitenschreibproblem.

    Erfahrene DBAs denken vielleicht, dass MySQL bei einem Schreibfehler eine Wiederherstellung anhand des Redo-Logs durchführen kann. Dies ist eine Methode, aber es muss klar sein, dass im Redo-Protokoll die physische Änderung der Seite aufgezeichnet wird, z. B. Offset 800, Schreiben eines „aaaa“-Datensatzes. Wenn die Seite selbst beschädigt ist, macht es keinen Sinn, sie zu wiederholen. MySQL überprüft die Prüfsumme der Seite während des Wiederherstellungsprozesses. Die Prüfsumme dient dazu, die letzte Transaktionsnummer der Seite zu überprüfen. Wenn ein Problem beim teilweisen Schreiben der Seite auftritt, wurde die Seite beschädigt und die Transaktionsnummer auf der Seite kann nicht gefunden werden. Aus Sicht von InnoDB kann eine solche Datenseite die Prüfsummenüberprüfung nicht bestehen und kann nicht wiederhergestellt werden. Selbst wenn wir die Überprüfung erzwingen, können wir den Absturz nicht beheben, da einige der aktuellen Protokolltypen in InnoDB, von denen einige logische Operationen sind, nicht idempotent sein können.

    Um dieses Problem zu lösen, implementiert InnoDB einen doppelten Schreibpuffer. Kurz gesagt, schreibt es vor dem Schreiben der Datenseite zunächst die Datenseite an einen unabhängigen physischen Dateispeicherort (ibdata) und dann auf die Datenseite. Wenn der Computer heruntergefahren und neu gestartet wird und die Datenseite beschädigt ist, muss die Seite vor dem Anwenden des Redo-Protokolls durch eine Kopie der Seite wiederhergestellt werden. Anschließend wird das Redo-Protokoll erneut erstellt. Dies ist ein doppelter Schreibvorgang . Was die Double-Write-Technologie zur innodb-Speicher-Engine bringt, ist die Zuverlässigkeit der Datenseiten. Die Double-Write-Technologie wird unten analysiert

    如上图所示,Double Write 由两部分组成,一部分是内存中的 double write buffer,大小为2MB,另一部分是物理磁盘上共享表空间连续的128个页,大小也为2MB。在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是通过 memcpy 函数将脏页先复制到内存中的该区域,之后通过 double write buffer 再分两次,每次1MB顺序地写入共享表空间的物理磁盘上,然后马上调用 fsync 函数,同步磁盘,避免操作系统缓冲写带来的问题。在完成double write 页的写入后,再将 double wirite buffer 中的页写入各个表空间文件中。

    在这个过程中,doublewrite 是顺序写,开销并不大,在完成 doublewrite 写入后,在将 double write buffer写入各表空间文件,这时是离散写入。

    如果操作系统在将页写入磁盘的过程中发生了崩溃,在恢复过程中,InnoDB 存储引擎可以从共享表空间中的double write 中找到该页的一个副本,将其复制到表空间文件中,再应用重做日志。

    InnoDB 存储引擎第二部分:后台线程

    IO 线程

    在 InnoDB 中使用了大量的 AIO(Async IO) 来做读写处理,这样可以极大提高数据库的性能。在 InnoDB 1.0 版本之前共有4个 IO Thread,分别是 write,read,insert buffer和log thread,后来版本将 read thread和 write thread 分别增大到了4个,一共有10个了。

    • - read thread : 负责读取操作,将数据从磁盘加载到缓存page页。4个

    • - write thread:负责写操作,将缓存脏页刷新到磁盘。4个

    • - log thread:负责将日志缓冲区内容刷新到磁盘。1个

    • - insert buffer thread :负责将写缓冲内容刷新到磁盘。1个

    Purge 线程

    事务提交之后,其使用的 undo 日志将不再需要,因此需要 Purge Thread 回收已经分配的 undo 页。show variables like '%innodb*purge*threads%';

    Page Cleaner 线程

    作用是将脏数据刷新到磁盘,脏数据刷盘后相应的 redo log 也就可以覆盖,即可以同步数据,又能达到 redo log 循环使用的目的。会调用write thread线程处理。show variables like '%innodb*page*cleaners%';

    InnoDB 存储引擎第三部分:磁盘文件

    InnoDB 的主要的磁盘文件主要分为三大块:一是系统表空间,二是用户表空间,三是 redo 日志文件和归档文件。

    二进制文件(binlong)等文件是 MySQL Server 层维护的文件,所以未列入 InnoDB 的磁盘文件中。

    系统表空间和用户表空间

    系统表空间包含 InnoDB 数据字典(元数据以及相关对象)并且 double write buffer , change buffer , undo logs 的存储区域。

    系统表空间也默认包含任何用户在系统表空间创建的表数据和索引数据。

    系统表空间是一个共享的表空间,因为它是被多个表共享的。

    系统表空间是由一个或者多个数据文件组成。默认情况下,1个初始大小为10MB,名为 ibdata1 的系统数据文件在MySQL的data目录下被创建。用户可以使用 innodb_data_file_path 对数据文件的大小和数量进行配置。

    innodb_data_file_path 的格式如下:

    innodb_data_file_path=datafile1[,datafile2]...

    用户可以通过多个文件组成一个表空间,同时制定文件的属性:

    innodb_data_file_path = /db/ibdata1:1000M;/dr2/db/ibdata2:1000M:autoextend

    这里将 /db/ibdata1 和 /dr2/db/ibdata2 两个文件组成系统表空间。如果这两个文件位于不同的磁盘上,磁盘的负载可能被平均,因此可以提高数据库的整体性能。两个文件的文件名之后都跟了属性,表示文件 ibdata1 的大小为1000MB,文件 ibdata2 的大小为1000MB,而且用完空间之后可以自动增长。

    设置 innodb_data_file_path 参数之后,所有基于 InnoDB 存储引擎的表的数据都会记录到该系统表空间中,如果设置了参数 innodb_file_per_table ,则用户可以将每个基于 InnoDB 存储引擎的表产生一个独立的用户空间。

    用户表空间的命名规则为:表名.ibd。通过这种方式,用户不用将所有数据都存放于默认的系统表空间中,但是用户表空间只存储该表的数据、索引和插入缓冲BITMAP等信息,其余信息还是存放在默认的系统表空间中。

    下图显示 InnoDB 存储引擎对于文件的存储方式,其中frm文件是表结构定义文件,记录每个表的表结构定义。

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Redo-Protokolldateien und Archivdateien

    Standardmäßig gibt es zwei Dateien mit den Namen ib_logfile0 und ib_logfile1 im Datenverzeichnis der InnoDB-Speicher-Engine. Dies ist die Redo-Protokolldatei für die InnoDB-Speicher-Engine.

    Wenn in der Datenspeicherdatei von InnoDB ein Fehler auftritt, kann die Redo-Log-Datei hilfreich sein. Die InnoDB-Speicher-Engine kann Redo-Log-Dateien verwenden, um Daten in den richtigen Zustand wiederherzustellen und so die Richtigkeit und Integrität der Daten sicherzustellen.

    Jede InnoDB-Speicher-Engine verfügt über mindestens 1 Redo-Log-Datei und jede Dateigruppe verfügt über mindestens 2 Redo-Log-Dateien sowie die Standarddateien ib_logfile0 und ib_logfile1.

    Um eine höhere Zuverlässigkeit zu erreichen, können Benutzer mehrere Spiegelprotokollgruppen einrichten und verschiedene Dateigruppen auf verschiedenen Festplatten platzieren, um die hohe Verfügbarkeit von Redo-Protokollen zu verbessern.

    Jede Redo-Log-Datei in der Log-Gruppe hat die gleiche Größe und arbeitet nach dem Prinzip des [Schleifenschreibens]. Die InnoDB-Speicher-Engine schreibt zuerst Redo-Log-Datei 1. Wenn die Datei voll ist, wechselt sie zu Redo-Log-Datei 2. Wenn Redo-Log-Datei 2 ebenfalls voll ist, wechselt sie zu Redo-Log-Datei 1.

    Benutzer können Innodb_log_file_size verwenden, um die Größe der Redo-Log-Datei festzulegen, was einen großen Einfluss auf die Leistung der InnoDB-Speicher-Engine hat.

    Wenn die Redo-Log-Datei zu groß eingestellt ist, kann die Wiederherstellung bei Datenverlust lange dauern. Wenn sie hingegen zu klein eingestellt ist, ist die Redo-Log-Datei zu klein, was zu häufigen Problemen führt Aktualisierung von Checkpoint-basierten Prüfungen. Fehlerhafte Seiten werden auf die Festplatte übertragen, was zu Leistungsschwankungen führt.

    Redo-Log-Flush-Mechanismus

    InnoDB folgt zwei Regeln: WAL (Write-Ahead-Redo-Log) und Force-Log-at-Commit zum Flushen von Datendateien und Protokolldateien, die beide die Haltbarkeit von Transaktionen gewährleisten. WAL erfordert, dass das Protokoll im Speicher zuerst auf die Festplatte geschrieben wird, bevor Datenänderungen auf die Festplatte geschrieben werden. Force-log-at-commit erfordert, dass beim Festschreiben einer Transaktion alle generierten Protokolle auf die Festplatte geleert werden Die Aktualisierung ist erfolgreich. Wenn die Datenbank abstürzt, bevor die Daten im Pufferpool auf der Festplatte aktualisiert werden, kann die Datenbank die Daten beim Neustart aus dem Protokoll wiederherstellen.

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Wie in der Abbildung oben gezeigt, schreibt InnoDB beim Ändern von Daten im Pufferpool zunächst die relevanten Änderungen in den Redo-Log-Puffer und schreibt sie dann pünktlich (z. B. pro Sekunde) auf die Festplatte Aktualisierungsmechanismus) oder wenn die Transaktion festgeschrieben wird, was dem Force-Log-at-Commit-Prinzip entspricht. Erst nachdem das Redo-Protokoll auf die Festplatte geschrieben wurde, werden die geänderten Daten im Pufferpool entsprechend auf die Festplatte geschrieben der Checkpoint-Mechanismus, der dem WAL-Prinzip entspricht.

    Im Checkpoint-Timing-Mechanismus wird davon ausgegangen, dass die Redo-Log-Datei voll ist. Wenn die Redo-Log-Datei daher zu klein und häufig voll ist, führt dies häufig dazu, dass der Checkpoint die geänderten Daten schreibt. in die Festplatte, was zu Leistungsschwankungen führt.

    Das Dateisystem des Betriebssystems verfügt über einen Cache. Wenn InnoDB Daten auf die Festplatte schreibt, werden diese möglicherweise nur in den Cache des Dateisystems geschrieben, und es gibt keine wirkliche „Sicherheit“.

    Das Attribut innodb_flush_log_at_trx_commit von InnoDB kann das Verhalten von InnoDB jedes Mal steuern, wenn eine Transaktion festgeschrieben wird. Wenn der Attributwert 0 ist und die Transaktion festgeschrieben wird, wird das Redo-Protokoll nicht geschrieben, sondern wartet darauf, dass der Hauptthread rechtzeitig schreibt. Wenn der Attributwert 1 ist, wird das Redo-Protokoll geschrieben in die Datei schreiben Das System speichert und ruft fsync des Dateisystems auf, um die Daten im Dateisystempuffer tatsächlich in den Festplattenspeicher zu schreiben und sicherzustellen, dass kein Datenverlust auftritt. Wenn der Attributwert 2 ist, wird auch die Protokolldatei geschrieben beim Festschreiben der Transaktion in den Cache, ruft jedoch nicht fsync auf, sondern lässt das Dateisystem bestimmen, wann der Cache auf die Festplatte geschrieben werden soll.

    Der Löschmechanismus des Protokolls ist in der folgenden Abbildung dargestellt:

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Innodb_flush_log_at_commit ist ein grundlegender Parameter für die InnoDB-Leistungsoptimierung, der die Schreibeffizienz und Datensicherheit von InnoDB betrifft. Wenn der Parameterwert 0 ist, ist die Schreibeffizienz am höchsten, aber die Datensicherheit ist am niedrigsten; wenn der Parameterwert 1 ist, ist die Schreibeffizienz am niedrigsten, aber die Datensicherheit ist am höchsten; , beide liegen auf einem mittleren Niveau, und es wird allgemein empfohlen, das Attribut zu setzen. Der Wert wird für eine höhere Sicherheit auf 1 gesetzt, und nur wenn er auf 1 gesetzt ist, kann die Haltbarkeit der Transaktion garantiert werden.

    Verwenden Sie eine UPDATE-Anweisung, um mehr über die InnoDB-Speicher-Engine zu erfahren.

    Anhand der obigen Einführung in die grundlegende Architektur der InnoDB-Speicher-Engine analysieren wir den spezifischen Prozess einer UPDATE-Datenaktualisierung.

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Wir unterteilen dieses Bild in einen oberen und einen unteren Teil. Der obere Teil ist der Verarbeitungsablauf der MySQL-Serverschicht und der untere Teil ist der Verarbeitungsablauf der MySQL InnoDB-Speicher-Engine.

    Verarbeitungsablauf der MySQL Server-Ebene

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Dieser Teil des Verarbeitungsablaufs hat nichts damit zu tun, welche Speicher-Engine von der Serverschicht verarbeitet wird. Die spezifischen Schritte sind wie folgt:

    • Verschiedene Benutzervorgänge lösen die SQL-Ausführung im Hintergrund über den Datenbankverbindungspool aus das kommt mit dem Webprojekt: wie dbcp, c3p0, druid usw., stellen Sie eine Netzwerkverbindung mit dem Datenbankverbindungspool des Datenbankservers her

    • Nachdem der Thread im Datenbankverbindungspool die Anfrage abhört, wird er antwortet dem Abfrageparser über die SQL-Schnittstelle mit der empfangenen SQL-Anweisung und die Abfrage analysiert. Der Server analysiert die SQL gemäß der SQL-Syntax, um zu bestimmen, welche Felder welcher Tabelle abgefragt werden sollen und welche Abfragebedingungen gelten

    • wird dann vom Abfrageoptimierer verarbeitet, um den optimalen Satz von Ausführungsplänen für das Quadrat auszuwählen

    • und dann der Executor, der für den Aufruf einer Reihe von Schnittstellen der Speicher-Engine verantwortlich ist, den Plan ausführt und die Ausführung des gesamten SQL abschließt Dieser Teil des Prozesses stimmt im Wesentlichen mit der oben analysierten Analyse eines Select-Anfrageverarbeitungsprozesses überein.

    Verarbeitungsablauf der InnoDB-Speicher-Engine

    Die spezifische Ausführungsanweisung muss von der Speicher-Engine abgeschlossen werden, wie in der Abbildung oben gezeigt: Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Aktualisieren Sie diese Daten mit der ID = 10 in der Benutzertabelle , wenn gepuffert Wenn sich kein solches Datenelement im Pool befindet, müssen zuerst die Originaldaten der aktualisierten Daten von der Festplatte in den Pufferpool geladen werden.

    • Gleichzeitig werden diese Daten zunächst gesperrt, um die Sicherheit gleichzeitig aktualisierter Daten zu gewährleisten, um zu verhindern, dass andere Transaktionen aktualisiert werden.

    • Dann sichern Sie den Wert vor der Aktualisierung und schreiben Sie ihn in das Rückgängig-Protokoll (um das Abrufen alter Daten zu erleichtern, wenn die Transaktion zurückgesetzt wird). Die Aktualisierungsanweisung speichert beispielsweise den Wert vor dem aktualisierten Feld.

    • Aktualisieren Sie die Cache-Daten im Pufferpool auf die neuesten Daten, dann sind die Daten im Speicher zu diesem Zeitpunkt fehlerhafte Daten (die Daten im Speicher und die Daten auf der Festplatte sind inkonsistent)

    ⾄Damit ist die Pufferung abgeschlossen. Der Ausführungsprozess im Pool (wie oben gezeigt).

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-EngineNachdem die Daten im Pufferpool aktualisiert wurden, müssen Sie diese Aktualisierungsinformationen nacheinander in das Redo-Protokoll schreiben, da die Daten im Speicher geändert wurden, die Daten auf der Festplatte jedoch nicht Wenn MySQL ausgefallen ist, gehen die geänderten Daten im Speicher unweigerlich verloren. Das Redo-Protokoll zeichnet auf, welche Änderungen Sie an den Daten vorgenommen haben, z. B. „Der Wert des Namensfelds wird im Datensatz von „id=“ auf „xxx“ geändert 10"" ist ein Protokoll, das zur Wiederherstellung Ihrer aktualisierten Daten verwendet wird, wenn MySQL plötzlich abstürzt. Bitte beachten Sie jedoch, dass Redo Log zu diesem Zeitpunkt noch nicht in der Protokolldatei abgelegt wurde.

    Ich denke gerade über eine Frage nach: Was passiert, wenn MySQL ausfällt, bevor die Transaktion übermittelt wird?

    Wir wissen oben, dass wir die Speicherdaten bisher geändert und dann den Redo-Log-Puffer-Protokollpuffer aufgezeichnet haben. Wenn MySQL zu diesem Zeitpunkt abstürzt, gehen die Speicherdaten und Redo-Log-Pufferdaten verloren, aber das spielt keine Rolle Die Daten gehen zu diesem Zeitpunkt verloren, da eine Aktualisierung erfolgt. Wenn die Anweisung die Transaktion nicht übermittelt hat, bedeutet dies, dass sie zu diesem Zeitpunkt nicht erfolgreich ausgeführt wurde, obwohl MySQL ausgefallen ist und die Daten im Speicher verloren gegangen sind dass die Daten auf der Festplatte weiterhin so bleiben, wie sie sind.

    Der nächste Schritt besteht darin, die Transaktion festzuschreiben. Zu diesem Zeitpunkt wird das Redo-Log gemäß einer bestimmten Strategie aus dem Redo-Log-Puffer geleert. Zu diesem Zeitpunkt wird diese Strategie über innodb_flush_log_at_trx_commit konfiguriert.

    innodb_flush_log_at_trx_commit=0, was bedeutet, dass beim Senden einer Transaktion die Daten im Redo-Log-Puffer nicht in die Festplattendatei geleert werden. Zu diesem Zeitpunkt haben Sie möglicherweise die Transaktion gesendet, und als Ergebnis ist MySQL ausgefallen und dann alles Die Daten im Speicher gehen verloren, daher ist dieser Ansatz nicht ratsam.

    innodb_flush_log_at_trx_commit=1, das Redo-Log wird aus dem Speicher in die Festplattendatei geleert. Solange die Transaktion erfolgreich übermittelt wird, muss sich das Redo-Log auf der Festplatte befinden, sodass die Daten wiederhergestellt werden können, wenn MySQL zu diesem Zeitpunkt abstürzt basierend auf dem Redo-Log.

    innodb_flush_log_at_trx_commit=2: Schreiben Sie beim Festschreiben einer Transaktion das Redo-Protokoll in den Betriebssystem-Cache, der der Festplattendatei entspricht, anstatt die Festplattendatei direkt einzugeben. Es kann 1 Sekunde dauern, bis die Daten im Betriebssystem-Cache in die Festplattendatei geschrieben werden . Gehen Sie hinein.

    Wenn eine Transaktion übermittelt wird, wird gleichzeitig das Binlog geschrieben. Es gibt auch einen sync_binlog-Parameter, der die Binlog-Flushing-Strategie steuern kann. Zu diesem Zeitpunkt ist Wenn Sie das Binlog auf die Festplatte schreiben, wird es tatsächlich nicht direkt in die Festplattendatei eingegeben, sondern in den Betriebssystem-Cache-Speichercache. Um sicherzustellen, dass keine Daten verloren gehen, konfigurieren wir im Allgemeinen eine Double-1-Strategie und wählen 1 sowohl für die Redo-Log- als auch für die Binlog-Festplattenplatzierungsstrategie.

    Nachdem das Binlog platziert wurde, werden der Binlog-Dateiname, die Dateipfadinformationen und die Commit-Markierung in der Synchronisierungsreihenfolge in das Redo-Protokoll geschrieben. Die Bedeutung dieses Schritts besteht darin, das Redo-Protokoll mit dem Binlog-Protokoll konsistent zu halten. Die Commit-Markierung ist ein wichtiges Kriterium, um festzustellen, ob eine Transaktion erfolgreich übermittelt wurde. Wenn MySQL beispielsweise nach der erfolgreichen Ausführung von Schritt 5 oder Schritt 6 abstürzt, liegt dieses Mal daran, dass im Redo-Log keine endgültige Transaktions-Commit-Markierung vorhanden ist, also diese Transaktion kann als erfolglos beurteilt werden. Es wird nicht gesagt, dass in der Redo-Protokolldatei ein Protokoll dieses Updates vorhanden ist, aber in der Binlog-Protokolldatei gibt es kein Protokoll dieses Updates, sodass kein Problem mit Dateninkonsistenzen auftritt.

    Nach Abschluss der oben genannten Schritte wurden die Speicherdaten geändert, die Transaktion übermittelt und das Protokoll auf der Festplatte abgelegt, die Festplattendaten wurden jedoch nicht gleichzeitig geändert. Im Hintergrund der InnoDB-Speicher-Engine befindet sich ein E/A-Thread. Während der Zeit mit geringer Spitzenbelastung der Datenbank werden die Daten im Pufferpool durch Transaktionen aktualisiert, hatten aber noch keine Zeit, auf die Festplatte geschrieben zu werden (schmutzige Daten). Da die Festplattendaten und Speicherdaten nicht mehr verfügbar sind (konsistent), werden sie auf die Festplatte geleert, um die Persistenz der Transaktion abzuschließen.

    Damit der Schreibprozess von InnoDB durch das Bild unten dargestellt werden kann

    Detaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine

    Empfohlenes Lernen: MySQL-Video-Tutorial

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der spannenden MySQL-Architektur und des Wissens über die InnoDB-Speicher-Engine. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen