1.Sperren? 1.1 Was ist ein Schloss? Die eigentliche Bedeutung eines Schlosses ist: ein verschlossener Gegenstand, der mit einem Schlüssel oder Code geöffnet werden kann. Sperren in Computern werden im Allgemeinen verwendet, um den gleichzeitigen Zugriff auf gemeinsam genutzte Ressourcen zu verwalten. Lock und synchronisiert, die unseren Java-Klassenkameraden bekannt sind, sind beispielsweise allgemeine Sperren. Natürlich gibt es in unserer Datenbank auch Sperren, um den gleichzeitigen Zugriff auf Ressourcen zu steuern. Dies ist einer der Unterschiede zwischen Datenbanken und Dateisystemen. 1.2 Warum müssen Sie Datenbanksperren verstehen? Generell gilt, dass allgemeine Entwickler bei der Verwendung der Datenbank über ausreichende Kenntnisse in DQL (Auswählen) und DML (Einfügen, Aktualisieren, Löschen) verfügen. Xiao Ming ist ein Java-Entwicklungsingenieur, der gerade seinen Abschluss gemacht hat und in einem Internetunternehmen arbeitet. Seine übliche Aufgabe besteht darin, die Anforderungen des PM zu erfüllen. Natürlich kann er beim Erfüllen der Anforderungen nicht auf das Framework von Spring, SpringMVC und Mybatis verzichten. Im Allgemeinen schreibt er das SQL also immer noch von Hand. Wenn er auf ein komplizierteres SQL stößt, sucht er im Internet bei Baidu. Für einige wichtige Vorgänge, z. B. Transaktionen, verwendet Xiao Ming Spring-Transaktionen, um Datenbanktransaktionen zu verwalten. Aufgrund der geringen Datenmenge sind derzeit keine verteilten Transaktionen beteiligt. Xiao Ming hatte in den letzten Monaten ein ruhiges Leben. Bis er eines Tages eine Anfrage erhielt. Der Händler hatte ein Konfigurationselement namens Rabattkonfigurationselement, mit dem er „Kaufe eins, bekomme eins gratis“, „Kaufe eins, bekomme zwei gratis“ und andere Regeln konfigurieren konnte. Natürlich wurden diese Konfigurationen stapelweise an das Backend übertragen. Dies stellte ein Problem dar, da jede Regel abgeglichen werden musste, um festzustellen, ob sie gelöscht, hinzugefügt oder geändert wurde. Dies machte die Backend-Logik komplizierter. Der schlaue Xiao Ming dachte sich eine Möglichkeit aus, die Konfiguration des Händlers direkt zu löschen und sie dann alle hinzuzufügen. Xiao Ming schloss die Entwicklung sofort ab und brachte sie erfolgreich auf den Markt. Beim ersten Start war alles in Ordnung, in den Protokollen traten jedoch häufig MySQL-Insert-Deadlock-Ausnahmen auf. Da Xiao Ming wenig Erfahrung hatte und zum ersten Mal auf dieses Problem stieß, fragte er den Veteranen in seiner Gruppe, Dahong. Als Dahong dieses Problem sah und sich seinen Code ansah, gab er einige Befehle aus, las einige Protokolle und fand das Problem sofort. Er sagte Xiao Ming: Dies liegt daran, dass beim Löschen eine Lückensperre hinzugefügt wird, Lückensperren jedoch miteinander kompatibel sind. Beim Einfügen neuer Daten wird jedoch die Sperre für die Einfügungsabsicht durch die Lückensperre blockiert, was zu einer gegenseitigen Belegung der Ressourcen auf beiden Seiten führt und zu einem Deadlock führt. Nachdem er das gehört hatte, schien Xiao Ming es zu verstehen, aber da Dahong viel zu tun hatte, war es unbequem, sie die ganze Zeit zu stören, also beschloss er, selbst darüber nachzudenken. Nach Feierabend dachte Xiao Ming über Dahongs Worte nach: Was ist eine Lückensperre und was ist eine Einfügesperre? Es scheint, dass Sie als Entwickler nicht nur SQL für die Datenbank schreiben können müssen, da Sie sonst einige schwierige Probleme nicht lösen können. Nachdem Xiao Ming darüber nachgedacht hatte, begab er sich auf den Weg ohne Wiederkehr, um die MySQL-Sperre zu erlernen. 2. InnoDB 2.1MySQL-Architektur Xiao Ming hatte es nicht eilig, dieses Wissen freizugeben. Er lernte zuerst die MySQL-Architektur kennen: Es lässt sich feststellen, dass Mysql aus Verbindungspoolkomponenten, Verwaltungsdiensten und Toolkomponenten, SQL-Schnittstellenkomponenten, Abfrageanalysekomponenten, Optimierungskomponenten, Pufferkomponenten, einer Plug-in-Speicher-Engine und physischen Dateien besteht. Xiao Ming entdeckte, dass die Speicher-Engine in MySQL in Form eines Plug-Ins bereitgestellt wird. In MySQL gibt es mehrere Speicher-Engines, und jede Speicher-Engine hat ihre eigenen Eigenschaften. Dann gab Xiao Ming in die Befehlszeile ein: Motoren anzeigen \G; Es stellt sich heraus, dass es sehr viele Arten von Motoren gibt. Geben Sie dann den folgenden Befehl ein, um die aktuelle Standard-Datenbank-Engine anzuzeigen: Variablen wie „%storage_engine%“ anzeigen; Xiao Ming bemerkte plötzlich, dass seine Datenbank InnoDB verwendete. Er erinnerte sich vage daran, dass er in der Schule von einer Engine namens MyISAM gehört hatte. Xiao Ming fragte sich, was der Unterschied zwischen den beiden war. Er suchte sofort einige Informationen heraus:
Xiao Ming verstand den Unterschied zwischen InnoDB und MyISAM ungefähr. Da er InnoDB verwendete, machte sich Xiao Ming darüber keine allzu großen Gedanken. 2.2 Transaktionsisolierung Bevor Xiao Ming das Thema Sperren studierte, erinnerte er sich an die Transaktionsisolierung von Datenbanken, die er in der Schule gelernt hatte. Tatsächlich besteht eine der Funktionen von Sperren in der Datenbank darin, eine Transaktionsisolierung zu erreichen. Die Isolierung von Transaktionen wird tatsächlich verwendet, um Probleme wie Dirty Reads, nicht wiederholbare Reads und Phantom Reads zu lösen. 2.2.1 Schmutziges Lesen Eine Transaktion liest aktualisierte Daten, die nicht von einer anderen Transaktion festgeschrieben wurden. Was bedeutet das?
Bei den Transaktionen A und B hat Transaktion A die Daten mit der ID 1 in der Benutzertabelle zu den Zeitpunkten 2 und 4 abgefragt, Transaktion B hat sie jedoch zum Zeitpunkt 3 geändert, sodass das Abfrageergebnis von Transaktion A in 4 tatsächlich das von Transaktion B geänderte Ergebnis war. Dadurch wird die Isolation in der Datenbank aufgehoben. 2.2.2 Nicht wiederholbares Lesen Das mehrmalige Lesen derselben Daten in derselben Transaktion kann zu unterschiedlichen Ergebnissen führen. Im Gegensatz zu Dirty Reads handelt es sich bei den hier gelesenen Daten um die festgeschriebenen Daten.
Die in Transaktion B übermittelte Operation erfolgt vor der zweiten Abfrage von Transaktion A, das Aktualisierungsergebnis von Transaktion B wird jedoch immer noch gelesen, wodurch auch die Isolation der Transaktion zerstört wird. 2.2.3 Phantom-Lesevorgänge Eine Transaktion liest die Einfügedaten, die von einer anderen Transaktion festgeschrieben wurden.
In Transaktion A wurden zwei Abfragen für IDs größer als 1 durchgeführt. In der ersten Abfrage waren keine Daten im Ergebnis enthalten. Da Transaktion B jedoch Daten mit ID=2 eingefügt hat, konnte Transaktion A in der zweiten Abfrage die in Transaktion B eingefügten Daten finden. Isolation bei Transaktionen:
Xiao Ming bemerkte beim Sammeln von Informationen, dass InnoDB sich ein wenig von anderen Datenbanken unterscheidet. Das wiederholbare Lesen von InnoDB kann tatsächlich Phantom-Lesevorgänge lösen. Xiao Ming dachte: Dieses InnoDB ist ziemlich großartig. Ich muss mir genauer ansehen, wie es funktioniert. 2.3 InnoDB-Sperrtypen Xiao Ming versteht zunächst die gängigen Sperrtypen in MySQL: 2.3.1 S oder X In InnoDb sind zwei Standardsperren auf Zeilenebene implementiert, die man sich einfach als zwei Lese-/Schreibsperren vorstellen kann:
Die vertikale Achse stellt die vorhandenen Sperren dar und die horizontale Achse die Sperren, die erworben werden sollen.
2.3.2 Absichtssperre Intention Locks sind Sperren auf Tabellenebene in InnoDB. Wie der Name schon sagt, werden sie verwendet, um auszudrücken, was eine Transaktion erreichen möchte. Absichtssperren werden unterteilt in:
Wozu dient dieses Schloss? Wozu brauchen Sie dieses Schloss? Wenn es keine solche Sperre gibt und Sie dieser Tabelle eine Tabellensperre hinzufügen möchten, besteht die allgemeine Vorgehensweise darin, jede Zeile zu durchsuchen, um festzustellen, ob eine Zeilensperre vorhanden ist. Dies ist zu ineffizient. Wenn wir jedoch eine absichtliche Sperre haben, müssen wir nur feststellen, ob eine absichtliche Sperre vorhanden ist, und müssen nicht jede Zeile einzeln scannen. InnoDB unterstützt Sperren auf Zeilenebene, daher kann die Kompatibilität von InnoDB-Sperren wie folgt erweitert werden:
2.3.3 Auto-Inkrement-Sperre Die Auto-Increment-Sperre ist ein spezieller Tabellensperrmechanismus, der die Leistung bei gleichzeitigen Einfügevorgängen verbessert. Dieses Schloss verfügt über mehrere Funktionen:
Nach MySQL Version 5.1.2 gibt es viele Optimierungen und die Art und Weise zum Erhöhen der Sperre kann je nach Modus angepasst werden. Xiao Ming sah dies und öffnete sein MySQL. Er stellte fest, dass es sich um Version 5.7 handelte. Daher gab er die folgende Anweisung ein, um den aktuellen Sperrmodus abzurufen: mysql> Variablen wie „innodb_autoinc_lock_mode“ anzeigen; +--------------------------+----------+ | Variablenname | Wert | +--------------------------+----------+ | innodb_autoinc_lock_mode | 2 | +--------------------------+----------+ 1 Zeile im Satz (0,01 Sek.) In MySQL hat innodbautoinclock_mode drei Konfigurationsmodi: 0, 1 und 2, die jeweils dem „traditionellen Modus“, „kontinuierlichen Modus“ und „verschachtelten Modus“ entsprechen.
2.4InnoDB-Sperralgorithmus Xiao Ming hat die Arten von Sperren in InnoDB kennengelernt, aber wie diese Sperren verwendet werden, hängt immer noch vom Sperralgorithmus ab. 2.4.1 Aufnahmesperre Die Datensatzsperre sperrt den Datensatz. Dabei ist zu erklären, dass hier der Indexdatensatz gesperrt wird und nicht unser eigentlicher Datensatz.
2.4.2 Lückensperre Wie der Name schon sagt, sperren Lückensperren die Lücken, nicht jedoch die Datensätze. Das Sperren der Lücke bedeutet, einen bestimmten Bereich zu sperren. Die Lückensperre wird auch als Lückensperre bezeichnet. Sie blockiert keine anderen Lückensperren, blockiert jedoch das Einfügen der Lückensperre. Dies ist auch der Schlüssel zum Verhindern von Phantom-Lesevorgängen. 2.4.3 Nächste-Tasten-Sperre Diese Sperre ist im Wesentlichen eine Datensatzsperre plus eine Lückensperre. Auf der RR-Isolationsebene (InnoDB-Standard) verwendet InnoDB diesen Algorithmus für Zeilenscansperren. Wenn der Abfragescan jedoch einen eindeutigen Index enthält, werden nur noch Datensatzsperren verwendet. Warum? Weil der eindeutige Index die Anzahl der Zeilen bestimmen kann, während andere Indizes die Anzahl der Zeilen nicht bestimmen können. Es ist möglich, dass die Daten dieses Indexes in anderen Transaktionen erneut hinzugefügt werden, was zu Phantom-Lesevorgängen führt.
2.4.4 Absichtssperre einfügen Offizielle Erklärung zum Einfügen der Absichtssperre in MySQL:
Es ist ersichtlich, dass die Einfügeabsichtssperre während des Einfügens generiert wird. Wenn mehrere Transaktionen gleichzeitig unterschiedliche Daten in dieselbe Indexlücke schreiben, muss nicht auf den Abschluss anderer Transaktionen gewartet werden, und es tritt keine Wartezeit für die Sperre auf. Angenommen, es gibt einen Datensatzindex mit den Schlüsselwerten 4 und 7 und verschiedene Transaktionen fügen jeweils 5 und 6 ein. Jede Transaktion generiert eine Einfügeabsichtssperre, die zwischen 4 und 7 hinzugefügt wird, und erhält eine exklusive Sperre für die eingefügte Zeile. Sie werden jedoch nicht gegenseitig gesperrt, da die Datenzeilen nicht in Konflikt stehen. Hierbei ist zu beachten, dass bei einer Lückensperre das Einfügen der Absichtssperre blockiert wird. 2.5 MVCC MVCC, Technologie zur Steuerung paralleler Mehrfachversionen. In InnoDB werden nach jeder Datensatzzeile zwei versteckte Spalten hinzugefügt, um die Erstellungsversionsnummer und die Löschversionsnummer aufzuzeichnen. Durch Versionsnummern und Zeilensperren wird die Parallelitätsleistung des Datenbanksystems verbessert. In MVCC können Lesevorgänge in zwei Typen unterteilt werden:
Beim Lesen von Snapshots auf der Isolationsebene RR ist der Erstellungszeitpunkt des Snapshots nicht der Zeitpunkt, zu dem die Transaktion gestartet wird, sondern der Zeitpunkt, zu dem die erste Select-Anweisung als Erstellungszeitpunkt des Snapshots verwendet wird. Bei nachfolgenden Auswahlvorgängen wird der Snapshot-Wert zum aktuellen Zeitpunkt gelesen. Auf der RC-Isolationsebene wird bei jedem Snapshot-Lesevorgang ein neuer Snapshot erstellt.
3. Sperranalyse Xiao Ming hat sich viel Grundwissen über MySQL-Sperren angeeignet und beschloss daher, eine Tabelle zu erstellen, um ein Experiment durchzuführen. Erstellen Sie zunächst eine einfache Benutzertabelle: CREATE TABLE `Benutzer` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(11) ZEICHENSATZ utf8mb4 STANDARD NULL, `Kommentar` varchar(11) ZEICHENSATZ utf8 STANDARD NULL, Primärschlüssel (`id`), SCHLÜSSEL `index_name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; Anschließend wurden mehrere experimentelle Daten eingefügt: Benutzerauswahl 20.333.333 einfügen; Benutzerauswahl 25.555.555 einfügen; Benutzerauswahl 20.999.999 einfügen; Datenbanktransaktionsisolierung wählt RR aus 3.1 Versuch 1 Xiao Ming startete zwei Transaktionen und führte Experiment 1 durch.
Xiao Ming startete zwei Transaktionen und gab die obigen Anweisungen ein. Dabei stellte er fest, dass die Zeit für Transaktion B tatsächlich abgelaufen war. Xiao Ming überprüfte dies und stellte fest, dass er die Zeile mit dem Namen = 555 eindeutig gesperrt hatte. Warum wurde ich also blockiert, als ich den Namen = 556 einfügen wollte? Also öffnete Xiao Ming die Befehlszeile und gab ein: Wählen Sie * aus information_schema.INNODB_LOCKS Es wurde festgestellt, dass in Transaktion A eine Next-Key-Sperre zu 555 hinzugefügt wird. Wenn Transaktion B einfügt, wird zuerst die Sperre mit der Einfügeabsicht eingefügt, sodass die folgende Schlussfolgerung gezogen wird: Es ist ersichtlich, dass Transaktion B aufgrund des Konflikts zwischen der Lückensperre und der Einfügeabsichtssperre blockiert ist. 3.2 Versuch 2 Xiao Ming stellte fest, dass die obige Abfragebedingung einen normalen nicht eindeutigen Index verwendete, also versuchte Xiao Ming es mit dem Primärschlüsselindex:
Es wird festgestellt, dass Transaktion B nicht blockiert ist. Was ist los? Xiao Ming ist etwas verwirrt. Gemäß der Routine von Experiment 1 sollte sie blockiert werden, da zwischen 25 und 30 eine Lückensperre vorhanden sein wird. Also verwendete Xiao Ming die Befehlszeile erneut und stellte fest, dass nur die X-Datensatzsperre hinzugefügt wurde. Es stellt sich heraus, dass der eindeutige Index die Datensatzsperre herabstuft. Der Grund dafür ist: Da der nicht eindeutige Index plus die Next-Key-Sperre die genaue Anzahl der Zeilen nicht bestimmen können, ist es möglich, dass andere Transaktionen während Ihrer Abfrage die Daten dieses Indexes erneut hinzufügen, was zur Zerstörung der Isolation führt, was ein Phantomlesen ist. Da der eindeutige Index die einzige Datenzeile angibt, müssen zum Auflösen von Phantomlesevorgängen keine Lückensperren hinzugefügt werden. 3.3 Versuch 3 Der Primärschlüsselindex und der nicht eindeutige Index wurden oben getestet. Es gibt ein weiteres Feld, das keinen Index hat. Was passiert, wenn es gesperrt ist?
Wenn Sie nicht indizierte Daten verwenden, werden allen gruppierten Indizes tatsächlich Next-Key-Sperren hinzugefügt. Wenn Sie also bei einer normalen Entwicklung keinen Index für die Abfragebedingungen haben, müssen Sie einen konsistenten Lesevorgang durchführen, d. h. einen gesperrten Lesevorgang. Dadurch wird der gesamten Tabelle ein Index hinzugefügt, wodurch alle anderen Transaktionen blockiert werden und die Datenbank grundsätzlich in einen nicht verfügbaren Zustand versetzt wird. 4. Zurück zum Unfall 4.1 Deadlock Nachdem Xiao Ming das Experiment beendet hatte, verstand er endlich einige grundlegende Sperrroutinen, aber was war der Deadlock, der zuvor online aufgetreten war? Deadlock: bezeichnet ein Phänomen, bei dem zwei oder mehr Transaktionen aufgrund von Konkurrenz um Ressourcen während der Ausführung aufeinander warten. Dies bedeutet, dass Deadlocks nur dann auftreten, wenn es Wartezeiten gibt. Deadlocks können durch die Beseitigung der Wartezeiten, z. B. durch ein Rollback der Transaktion, gelöst werden. Es gibt zwei Möglichkeiten, einen Deadlock zu beheben:
Wenn ein Rollback auftritt, wählt InnoDB normalerweise das Rollback von Transaktionen mit kleineren Gewichten, d. h. Transaktionen mit kleineren Undo-Werten. 4.2 Online-Probleme Xiao Ming verfügt über alle erforderlichen Grundkenntnisse und beginnt, dieses Problem in seiner lokalen Tabelle zu reproduzieren:
Sie können sehen, dass Transaktion A zurückgesetzt wird, während Transaktion B erfolgreich ausgeführt wird. Was ist zu jedem Zeitpunkt passiert? Zeitpunkt 2: Transaktion A löscht die Daten mit dem Namen = „777“. Sie muss dem Index 777 eine Next-Key-Sperre hinzufügen, die jedoch nicht existiert. Daher wird nur eine Lückensperre zwischen 555 und 999 hinzugefügt. In ähnlicher Weise fügt Transaktion B auch eine Lückensperre zwischen 555 und 999 hinzu. Spaltschlösser sind untereinander kompatibel. Zeitpunkt 3: Transaktion A führt einen Einfügevorgang aus und fügt zuerst eine Absichtssperre ein. Es gibt jedoch eine Lückensperre zwischen 555 und 999. Aufgrund des Konflikts zwischen der Einfügeabsichtssperre und der Lückensperre wird Transaktion A blockiert und wartet darauf, dass Transaktion B die Lückensperre freigibt. Transaktion B ist ähnlich und wartet darauf, dass Transaktion A die Lückensperre freigibt. Es wartet also eine A->B, B->A-Schleife. Zeitpunkt 4: Der Transaktionsmanager entscheidet sich für ein Rollback der Transaktion A und der Einfügevorgang der Transaktion B wird erfolgreich ausgeführt. 4.3 Fehlerbehebungen Xiao Ming hat dieses Problem schließlich gefunden, das auf die Lückensperre zurückzuführen ist. Jetzt müssen wir dieses Problem lösen. Der Grund für dieses Problem ist die Lückensperre, also lasst uns sie beseitigen:
Nach einiger Überlegung entschied sich Xiao Ming für die vierte Option, ließ sofort eine Reparatur durchführen und ging dann zur Beobachtung und Überprüfung online. Er stellte fest, dass der Fehler nicht mehr auftrat. Jetzt kann Xiao Ming endlich gut schlafen. 4.4 So verhindern Sie Deadlocks Durch grundlegendes Lernen und tägliche Erfahrung fasste Xiao Ming die folgenden Punkte zusammen:
endlich Aufgrund des begrenzten Platzes können viele Dinge nicht vollständig vorgestellt werden. Wenn Sie interessiert sind, können Sie Kapitel 6 von „MySQL Technology Insider – InnoDB Engine“ und Master Hes MySQL Lock Processing Analysis lesen. Das Niveau des Autors ist begrenzt. Wenn Fehler vorhanden sind, weisen Sie bitte darauf hin. Das ist alles für diesen Artikel. Ich hoffe, dass der Inhalt dieses Artikels für Ihr Studium oder Ihre Arbeit von gewissem Referenzwert ist. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM. Das könnte Sie auch interessieren:
|
<<: React+Amap ermittelt Breiten- und Längengrad in Echtzeit und lokalisiert die Adresse
>>: So installieren und konfigurieren Sie einen FTP-Server in CentOS8.0
Dieser Artikel beschreibt anhand eines Beispiels,...
Inhaltsverzeichnis 1. Selbstaufzählbare Eigenscha...
Da PostgreSQL kompiliert und installiert ist, müs...
<table id=" <%=var1%>">, der...
Es gibt zwei Möglichkeiten, mit Nginx mehrere Pro...
Schauen wir uns den Befehl zum Neustarten der Doc...
Inhaltsverzeichnis Anforderung: Abfrage laufender...
Bereits in den CSS2-Empfehlungen von 1998 verschwa...
Vorwort Heute habe ich MySQL installiert und fest...
FTP und SFTP werden häufig als Dateiübertragungsp...
Zusammenfassung HTML: Element plus V-Umhang CSS: ...
1. Im Allgemeinen ist MariaDB in CentOS standardm...
Das Ziel von Google mit Flutter bestand immer dar...
Vorwort Dieser Artikel verwendet die neuen Funkti...
Wenn ich im Internet surfe, sehe ich oft Websites...