Implementierung der MVCC-Mehrversions-Parallelitätskontrolle von MySQL

Implementierung der MVCC-Mehrversions-Parallelitätskontrolle von MySQL

1 Was ist MVCC

Der vollständige Name von MVCC lautet: Multiversion Concurrency Control. Es verarbeitet den Speicherlesevorgang innerhalb der Transaktion, wenn gleichzeitiger Zugriff auf die Datenbank bereitgestellt wird, um das Parallelitätsproblem zu vermeiden, dass Schreibvorgänge Lesevorgänge blockieren.

Beispiel: Programmierer A liest bestimmte Inhalte in der Datenbank und Programmierer B ändert diese Inhalte (vorausgesetzt, die Änderung erfolgt innerhalb einer Transaktion, die etwa 10 Sekunden dauert). A kann innerhalb dieser 10 Sekunden inkonsistente Daten sehen. Wie kann A immer konsistente Daten lesen, bevor B einen Commit durchführt?

Es gibt mehrere Möglichkeiten, damit umzugehen. Die erste ist die sperrenbasierte Parallelitätskontrolle. Wenn Programmierer B beginnt, die Daten zu ändern, sperrt er die Daten. Wenn Programmierer A die Daten zu diesem Zeitpunkt liest, stellt er fest, dass er sie nicht lesen kann und sich in einem Wartezustand befindet. Er kann die Daten erst lesen, nachdem B den Vorgang abgeschlossen hat. Dadurch wird sichergestellt, dass A keine inkonsistenten Daten liest, dies beeinträchtigt jedoch die Laufeffizienz des Programms. Es gibt noch eine weitere: MVCC. Wenn sich jeder Benutzer mit der Datenbank verbindet, sieht er einen Snapshot der Datenbank zu einem bestimmten Zeitpunkt. Bevor Bs Transaktion festgeschrieben wird, liest A immer einen Snapshot der Datenbank zu einem bestimmten Zeitpunkt und liest nicht die Datenänderungen in Bs Transaktion. Erst wenn Bs Transaktion festgeschrieben wird, kann A Bs Änderungen lesen.

Eine Datenbank, die MVCC unterstützt, überschreibt beim Aktualisieren bestimmter Daten die alten Daten nicht durch die neuen Daten, sondern kennzeichnet die alten Daten als veraltet und fügt an anderer Stelle eine neue Datenversion hinzu. Daher werden mehrere Versionen derselben Daten gespeichert, aber nur eine ist die aktuellste.

MVCC bietet eine Lösung für die Zeitkonsistenz. Beim Lesen von Transaktionen unter MVCC wird normalerweise ein Zeitstempel oder eine Transaktions-ID verwendet, um zu bestimmen, auf welchen Datenbankstatus und auf welche Datenversion zugegriffen werden soll. Lesetransaktionen und Schreibtransaktionen sind voneinander isoliert und beeinflussen sich nicht gegenseitig. Angenommen, auf dieselben Daten wird sowohl von Lese- als auch von Schreibtransaktionen zugegriffen. Tatsächlich erstellt die Schreibtransaktion eine neue Datenversion, während die Lesetransaktion auf die alte Datenversion zugreift. Die Lesetransaktion greift erst dann auf die neue Datenversion zu, wenn die Schreibtransaktion festgeschrieben ist.

Es gibt zwei Möglichkeiten, MVCC zu implementieren. Die erste Möglichkeit besteht darin, mehrere Versionen von Datensätzen in der Datenbank zu speichern. Wenn diese verschiedenen Datenversionen nicht mehr benötigt werden, fordert der Garbage Collector diese Datensätze zurück. Diese Methode wird von PostgreSQL und Firebird/Interbase übernommen. SQL Server verwendet einen ähnlichen Mechanismus, der Unterschied besteht jedoch darin, dass die Daten der alten Version nicht in der Datenbank gespeichert werden, sondern in einer anderen Datenbank als der Hauptdatenbank, tempdb. Die zweite Implementierungsmethode speichert nur die neueste Version der Daten in der Datenbank, rekonstruiert aber dynamisch die alte Version der Daten, wenn Undo verwendet wird. Diese Methode wird von Oracle und MySQL/InnoDB verwendet.

2. InnoDBs MVCC-Implementierungsmechanismus

MVCC kann als eine Variante der Zeilensperre betrachtet werden, die in vielen Fällen Sperrvorgänge vermeiden kann und somit einen geringeren Overhead verursacht. Die meisten MVCC-Implementierungen implementieren nicht blockierende Lesevorgänge, und Schreibvorgänge sperren nur die erforderlichen Zeilen. Die MVCC-Implementierung von InnoDB wird durch das Speichern eines Daten-Snapshots zu einem bestimmten Zeitpunkt erreicht. Unabhängig davon, wie lange die Ausführung einer Transaktion dauert, sind die darin angezeigten Daten konsistent. Das heißt, dass sich Transaktionen während der Ausführung nicht gegenseitig beeinflussen. Nachfolgend beschreiben wir kurz die Implementierung von MVCC in InnoDB.

InnoDBs MVCC wird implementiert, indem nach jeder Datensatzzeile zwei versteckte Spalten gespeichert werden: Eine Spalte speichert die Erstellungszeit der Zeile und die andere die Ablaufzeit (Löschzeit) der Zeile. Natürlich ist die Zeit hier kein Zeitstempel, sondern eine Systemversionsnummer. Jedes Mal, wenn eine neue Transaktion gestartet wird, erhöht sich die Systemversionsnummer. Auf der RR-Isolationsebene funktioniert MVCC wie folgt:

Wählen Sie die Operation aus.

InnoDB sucht nur nach Datenzeilen, deren Versionen vor (oder gleich) der aktuellen Transaktionsversion sind. Es wird sichergestellt, dass die von einer Transaktion gelesenen Zeilen entweder vor Beginn der Transaktion vorhanden sind oder Datensätze sind, die von der Transaktion selbst eingefügt oder geändert wurden.

Die gelöschte Version einer Zeile ist entweder undefiniert oder größer als die aktuelle Transaktionsversionsnummer. Sie können sicherstellen, dass von einer Transaktion gelesene Zeilen nicht vor Beginn der Transaktion gelöscht wurden.

Einfügevorgang. Speichert die aktuelle Versionsnummer der neu eingefügten Zeile als Zeilenversionsnummer.

Löschvorgang. Speichert die aktuelle Versionsnummer der gelöschten Zeile als Löschzeichen.

Aktualisierungsvorgang. Es handelt sich um eine Kombination aus Einfüge- und Löschvorgängen. Die eingefügte Zeile speichert die aktuelle Versionsnummer als Zeilenversionsnummer, und das Löschen speichert die aktuelle Versionsnummer als Löschmarkierung in der ursprünglichen Zeile.

Da die alten Daten nicht wirklich gelöscht werden, müssen sie bereinigt werden. InnoDB startet einen Hintergrundthread, um die Bereinigung durchzuführen. Die konkrete Regel besteht darin, die Zeilen zu löschen, deren Versionsnummer kleiner als die aktuelle Systemversion ist. Dieser Vorgang wird als Bereinigung bezeichnet.

3. Ein einfaches Beispiel

Tabelle erstellen yang( 
    ID int Primärschlüssel auto_increment, 
    Name varchar(20));
}

Gehen Sie davon aus, dass die Systemversionsnummer bei 1 beginnt.

EINFÜGEN

InnoDB speichert die aktuelle Systemversionsnummer als Versionsnummer für jede neu eingefügte Zeile.
Die erste Transaktions-ID ist 1;

Transaktion starten;
in Yang-Werte einfügen (NULL, „Yang“);
in Yang-Werte einfügen (NULL, „lang“);
in Yang-Werte einfügen (NULL, „fei“);
begehen;

Die entsprechende Tabelle in den Daten sieht wie folgt aus (die letzten beiden Spalten sind ausgeblendete Spalten und wir können sie über die Abfrageanweisung nicht sehen)

WÄHLEN

InnoDB prüft jede Zeile anhand der folgenden beiden Bedingungen:
a. InnoDB sucht nur nach Datenzeilen, deren Version älter ist als die aktuelle Transaktionsversion (das heißt, die Systemversionsnummer der Zeile ist kleiner oder gleich der Systemversionsnummer der Transaktion). Dadurch wird sichergestellt, dass die von der Transaktion gelesenen Zeilen entweder vor Beginn der Transaktion vorhanden sind oder von der Transaktion selbst eingefügt oder geändert werden.
b. Die gelöschte Version der Zeile ist entweder nicht definiert oder größer als die aktuelle Transaktionsversionsnummer. Dadurch wird sichergestellt, dass die von der Transaktion gelesene Zeile nicht gelöscht wurde, bevor die Transaktion startet.
Als Abfrageergebnisse können nur Datensätze zurückgegeben werden, die sowohl a als auch b erfüllen.

LÖSCHEN

InnoDB speichert für jede gelöschte Zeile die aktuelle Systemversionsnummer (Transaktions-ID) als Löschkennung.
Siehe die folgende spezifische Beispielanalyse:
Die zweite Transaktion hat die ID 2;

Transaktion starten;
wähle * aus yang; //(1)
wähle * aus yang; //(2)
begehen;

Annahme 1

Angenommen, während der Ausführung der Transaktion mit der ID 2 wird beim Erreichen von (1) eine weitere Transaktion mit der ID 3 durchgeführt, die einen Datensatz in die Tabelle einfügt.
Die dritte Transaktions-ID ist 3;

Transaktion starten;
in Yang-Werte einfügen (NULL, „tian“);
begehen;

Die Daten in der Tabelle lauten wie folgt:

Anschließend wird (2) in Transaktion 2 ausgeführt. Da zum Erstellungszeitpunkt der Daten mit ID=4 (Transaktions-ID ist 3) die ID der aktuellen Transaktion 2 ist und InnoDB nur nach Datenzeilen mit Transaktions-IDs sucht, die kleiner oder gleich der aktuellen Transaktions-ID sind, wird die Datenzeile mit ID=4 in (2) in Transaktion 2 nicht abgerufen. Die von den beiden Select-Anweisungen in Transaktion 2 abgerufenen Daten sind nur wie folgt:

Annahme 2

Nehmen wir an, dass während der Ausführung der Transaktions-ID 2 gerade (1) ausgeführt wurde. Nehmen wir an, dass die Transaktion, nachdem sie Transaktion 3 ausgeführt hat, anschließend Transaktion 4 ausführt.
Die vierte Transaktion:

Transaktion starten;  
Löschen aus Yang, wo ID=1;
begehen;

Zu diesem Zeitpunkt lauten die Tabellen in der Datenbank wie folgt:

Als nächstes wird Transaktion (2) mit der Transaktions-ID 2 ausgeführt. Gemäß der SELECT-Suchbedingung wird nach Zeilen gesucht, deren Erstellungszeit (ID der Erstellungstransaktion) kleiner als die aktuelle Transaktions-ID und deren Löschzeit (ID der Löschtransaktion) größer als die aktuelle Transaktions-ID ist. Die Zeile mit der ID=4 wurde oben erwähnt, und die Zeile mit der ID=1 hat eine Löschzeit (ID der Löschtransaktion), die größer als die aktuelle Transaktions-ID ist. Daher sucht das select * from yang in Transaktion 2 (2) auch nach den Daten mit der ID=1. Daher lauten die von den beiden select-Anweisungen in Transaktion 2 gesuchten Daten wie folgt:

AKTUALISIEREN
Wenn InnoDB UPDATE ausführt, fügt es tatsächlich eine neue Datensatzzeile ein und speichert deren Erstellungszeit als ID der aktuellen Transaktion. Außerdem speichert es die Löschzeit von der aktuellen Transaktions-ID in der zu UPDATENden Zeile.

Annahme 3
Angenommen, nach der Ausführung der Transaktion 2 (1) führen andere Benutzer die Transaktionen 3 und 4 aus. Zu diesem Zeitpunkt führt ein anderer Benutzer eine UPDATE-Operation für diese Tabelle aus:
Die fünfte Aufgabe:

Transaktion starten;
Aktualisieren Sie den festgelegten Namen = "Long", wobei "ID" = 2 ist.
begehen;

Nach dem Update-Prinzip wird eine neue Zeile erzeugt und in der Spalte Löschzeitpunkt der ursprünglich zu ändernden Spalte die Transaktions-ID ergänzt, so dass folgende Tabelle entsteht:

Fahren Sie mit der Ausführung von (2) der Transaktion 2 fort. Gemäß den Suchbedingungen der Select-Anweisung wird die folgende Tabelle erhalten:

Es wird das gleiche Ergebnis wie bei Transaktion 2 (1) ausgewählt.

Dies ist das Ende dieses Artikels über die Implementierung der MySQL MVCC-Mehrversions-Parallelitätskontrolle. Weitere relevante Inhalte zur MySQL MVCC-Mehrversions-Parallelitätskontrolle finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Implementierung der MySQL-Mehrversions-Parallelitätskontrolle MVCC
  • Detaillierte Erläuterung des MySQL Multi-Version Concurrency Control Mechanism (MVCC)-Quellcodes
  • Detaillierte Untersuchung der MySQL-Mehrversions-Parallelitätskontrolle MVCC
  • Analyse des zugrunde liegenden Prinzips der MySQL-Mehrversions-Parallelitätskontrolle MVCC
  • Implementierung von MySQL Multi-version Concurrency Control MVCC
  • Details zur Mysql MVCC-Mehrversions-Parallelitätssteuerung

<<:  Zusammenfassung der Benutzererfahrung

>>:  JavaScript-Funktion Currying

Artikel empfehlen

VScode Remote SSH-Remote-Bearbeitung und -Debugging von Code

Die neueste Insider-Version von Visual Studio Cod...

Vollständige Schritte zum Mounten einer neuen Datenfestplatte in CentOS7

Vorwort Ich habe gerade einen neuen VPS gekauft. ...

Detaillierte Erklärung der Schleifenverwendung in Javascript-Beispielen

Aus Langeweile habe ich ein paar einfache Übungen...

Detaillierte Erläuterung der Kapselung von JavaScript-Animationsfunktionen

Inhaltsverzeichnis 1. Prinzip der Animationsfunkt...

So konfigurieren Sie pseudostatisches und clientadaptives Nginx

Das Backend verwendet das Framework thinkphp3.2.3...

MySQL-langsame Abfrage pt-query-digest Analyse des langsamen Abfrageprotokolls

1. Einleitung pt-query-digest ist ein Tool zum An...

Bootstrap 3.0 - Schaltflächenstil für Lernnotizen

In diesem Artikel wird hauptsächlich der Stil der...

So passen Sie die Bash-Eingabeaufforderung in Linux an

Vorwort Wie wir alle wissen, ist Bash (die Bourne...

So erstellen Sie ein Tomcat-Image basierend auf Dockerfile

Dockerfile ist eine Datei, die zum Erstellen eine...

Lösung zum automatischen Stoppen des MySQL-Dienstes

Dieser Artikel stellt hauptsächlich die Lösung fü...

Detaillierte Beispiele zur Float-Verwendung in HTML/CSS

1. Grundlegende Anwendungsbeispiele für Float 1. ...

Tutorial zur Installation von MySQL 5.6 auf CentOS 6.5

1. Laden Sie das RPM-Paket für Linux herunter htt...

js realisiert den Lupeneffekt von Produkten auf Einkaufswebsites

In diesem Artikel wird der spezifische Code von j...