Hintergrund Apropos MySQL-Deadlock: Ich habe bereits eine grundlegende Einführung in MySQL-Sperren geschrieben. Informationen zu einigen grundlegenden MySQL-Sperren oder Deadlocks finden Sie in diesem Artikel darüber, warum Entwickler Datenbanksperren verstehen müssen. Aufgrund der oben genannten Erfahrungen dachte ich, ich könnte problemlos mit Deadlocks umgehen. Unerwarteterweise wurde an einem sonnigen Nachmittag ein weiterer Deadlock gemeldet, aber dieses Mal war es nicht so einfach, wie ich es mir vorgestellt hatte. Probleme traten erstmals auf Eines Nachmittags schlug das System plötzlich Alarm und warf eine Ausnahme: Bei näherem Hinsehen stellte sich heraus, dass es sich um ein abnormales Rollback der Transaktion handelte. Es hieß, dass das Rollback aufgrund eines Deadlocks erfolgte. Es stellte sich jedoch heraus, dass es sich um ein Deadlock-Problem handelte. Da ich einige Kenntnisse über MySQL-Sperren habe, begann ich, dieses Problem aktiv zu untersuchen. Suchen Sie zunächst in der Datenbank nach Innodb Status. Innodb Status zeichnet die Informationen zum letzten Deadlock auf. Geben Sie den folgenden Befehl ein: ENGINE-INNODB-STATUS ANZEIGEN Die Deadlock-Informationen lauten wie folgt und die SQL-Informationen werden einfach verarbeitet: ------------------------ Zuletzt erkannter Deadlock ------------------------ 2019-02-22 15:10:56 0x7eec2f468700 *** (1) TRANSAKTION: TRANSAKTION 2660206487, AKTIV 0 Sek. Startindex lesen MySQL-Tabellen in Verwendung 1, gesperrt 1 LOCK WAIT 2 Sperrstruktur(en), Heap-Größe 1136, 1 Zeilensperre(n) MySQL-Thread-ID 31261312, OS-Thread-Handle 139554322093824, Abfrage-ID 11624975750 10.23.134.92 erp_crm__6f73 wird aktualisiert /*id:3637ba36*/UPDATE tenant_config SET open_card_point = 0 wobei tenant_id = 123 *** (1) WARTEN AUF DIE GEWÄHRUNG DIESER SPERRE: Datensatzsperren, Bereichs-ID 1322, Seitennummer 534, N Bits 960, Index uidx_tenant der Tabelle „erp_crm_member_plan“. „tenant_config“ TRX-ID 2660206487, Sperrmodus X, Datensätze sperren, aber keine Lücken warten *** (2) TRANSAKTION: TRANSAKTION 2660206486, AKTIV 0 Sek. Startindex lesen MySQL-Tabellen in Verwendung 1, gesperrt 1 3 Sperrstruktur(en), Heap-Größe 1136, 2 Zeilensperren MySQL-Thread-ID 31261311, OS-Thread-Handle 139552870532864, Abfrage-ID 11624975758 10.23.134.92 erp_crm__6f73 wird aktualisiert /*id:3637ba36*/UPDATE tenant_config SET open_card_point = 0 wobei tenant_id = 123 *** (2) HÄLT DAS SCHLOSS: Datensatzsperren, Bereichs-ID 1322, Seitennummer 534, N Bits 960, Index uidx_tenant der Tabelle „erp_crm_member_plan“. „tenant_config“, TRX-ID 2660206486, Sperrmodus S *** (2) WARTEN AUF DIE GEWÄHRUNG DIESER SPERRE: Datensatzsperren, Bereichs-ID 1322, Seitennummer 534, N Bits 960, Index uidx_tenant der Tabelle „erp_crm_member_plan“. „tenant_config“ TRX-ID 2660206486, Sperrmodus X, Sperren für Datensätze, aber keine Lückenwartezeit *** WIR MACHEN DIE TRANSAKTION ZURÜCK (1) ------------ Lassen Sie mich dieses Deadlock-Protokoll kurz analysieren und erklären. Wenn Transaktion 1 die Update-Anweisung ausführt, muss sie in der Where-Bedingung die X-Sperre (Zeilensperre) für den uidx_tenant-Index erhalten. Transaktion 2 führt dieselbe Update-Anweisung aus und möchte auch die X-Sperre (Zeilensperre) für uidx_tenant erhalten. Dann tritt ein Deadlock auf und Transaktion 1 wird zurückgesetzt. Ich war damals verwirrt und erinnerte mich an die notwendigen Bedingungen für einen Deadlock: 1. Sich gegenseitig ausschließend. 2. Konditionen anfordern und einhalten. 3. Keine Entziehung der Bedingungen. 4. Warten Sie in einer Schleife. Aus dem Protokoll können wir ersehen, dass sowohl Transaktion 1 als auch Transaktion 2 um die Zeilensperre derselben Zeile konkurrieren, was sich ein wenig vom vorherigen zyklischen Sperrwettbewerb unterscheidet. Egal, wie Sie es betrachten, die zyklische Wartebedingung kann nicht erfüllt werden. Nach der Erinnerung eines Kollegen besteht die einzige Möglichkeit darin, den Geschäftscode und das Geschäftsprotokoll zur Fehlerbehebung zu verwenden, da das Deadlock-Protokoll nicht zur Fehlerbehebung verwendet werden kann. Die Logik dieses Codes ist wie folgt: öffentliche int saveTenantConfig(PoiContext poiContext, TenantConfigDO tenantConfig) { versuchen { gibt tenantConfigMapper.saveTenantConfig zurück (poiContext.getTenantId(), poiContext.getPoiId(), tenantConfig); } Fang (DuplicateKeyException e) { LOGGER.warn("[saveTenantConfig] Primärschlüsselkonflikt, aktualisiere den Datensatz. context:{}, config:{}", poiContext, tenantConfig); gibt tenantConfigMapper.updateTenantConfig(poiContext.getTenantId(), tenantConfig) zurück; } } Dieser Code bedeutet das Speichern einer Konfigurationsdatei. Wenn ein eindeutiger Indexkonflikt auftritt, wird er aktualisiert. Natürlich kann er nicht auf standardmäßige Weise geschrieben werden. Tatsächlich kann er verwendet werden einfügen in ... bei doppeltem Schlüssel-Update Derselbe Effekt kann erzielt werden, aber auch hiermit kommt es zu einem Deadlock. Mein Kollege hat mir nach dem Lesen des Codes das damalige Geschäftsprotokoll zugesendet. Sie können sehen, dass drei Protokolle gleichzeitig aufgetreten sind, was darauf hinweist, dass ein eindeutiger Indexkonflikt aufgetreten ist, die Aktualisierungsanweisung eingegeben wurde und anschließend ein Deadlock auftrat. An diesem Punkt scheint die Antwort endlich klarer zu werden. Betrachten wir nun unsere Tabellenstruktur wie folgt (vereinfacht): Tabelle „tenant_config“ erstellen ( `id` bigint(21) NICHT NULL AUTO_INCREMENT, `tenant_id` int(11) NICHT NULL, `open_card_point` int(11) DEFAULT NULL, Primärschlüssel (`id`), EINDEUTIGER SCHLÜSSEL `uidx_tenant` (`tenant_id`) ) ENGINE=InnoDB STANDARD CHARSET=utf8mb4 ROW_FORMAT=KOMPAKT Unsere tenant_id wird als eindeutiger Index verwendet und unsere Einfüge- und Aktualisierungsbedingungen basieren alle auf dem eindeutigen Index. AKTUALISIEREN Sie tenant_config SET open_card_point = 0 wobei tenant_id = 123 An diesem Punkt scheint es, dass das Sperren des eindeutigen Index während des Einfügens damit zusammenhängt. Als Nächstes fahren wir mit dem nächsten Schritt der eingehenden Analyse fort. Detaillierte Analyse Oben haben wir gesagt, dass drei Transaktionen in die Update-Anweisung eingehen. Um die Erklärung zu vereinfachen, müssen nur zwei Transaktionen gleichzeitig in die Update-Anweisung eingehen. Die folgende Tabelle zeigt unseren gesamten Prozess: Tipp: Die S-Sperre ist eine gemeinsam genutzte Sperre und die X-Sperre ist eine Mutex-Sperre. Im Allgemeinen schließen sich X-Sperren und S,X-Sperren gegenseitig aus, S-Sperren und S-Sperren jedoch nicht gegenseitig aus. Aus dem obigen Prozess können wir ersehen, dass der Schlüssel zu diesem Deadlock darin besteht, das S-Schloss zu erhalten. Warum müssen wir das S-Schloss erhalten, wenn wir es erneut einfügen? Weil wir einen eindeutigen Index ermitteln müssen? Wenn Sie auf der RR-Isolationsebene lesen möchten, handelt es sich um einen aktuellen Lesevorgang, sodass Sie tatsächlich eine S-Sperre hinzufügen müssen. Hier wird festgestellt, dass der eindeutige Schlüssel bereits vorhanden ist. Zu diesem Zeitpunkt wird die Ausführung der Aktualisierung durch die S-Sperren der beiden Transaktionen blockiert, wodurch der obige zirkuläre Wartezustand entsteht. Tipp: In MVCC besteht der Unterschied zwischen dem aktuellen Lesen und dem Snapshot-Lesen darin, dass beim aktuellen Lesen jedes Mal eine Sperre erforderlich ist (gemeinsame Sperre oder Mutex-Sperre können verwendet werden), um die neuesten Daten zu erhalten, während beim Snapshot-Lesen der Snapshot zu Beginn der Transaktion gelesen wird, was durch das Rückgängigmachen des Protokolls erreicht wird. Dies ist die Ursache für den gesamten Deadlock. Eine weitere Situation, in der dieser Deadlock auftreten kann, ist, wenn drei Einfügevorgänge gleichzeitig ausgeführt werden. Wenn die zuerst eingefügte Transaktion schließlich zurückgesetzt wird, kommt es auch bei den anderen beiden Transaktionen zu diesem Deadlock. Lösung Das Hauptproblem besteht darin, dass die S-Sperre entfernt werden muss. Hier sind drei Lösungen als Referenz:
Die erste Methode ist nicht sehr realistisch, schließlich lässt sich die Isolationsstufe nicht so einfach ändern. Die dritte Methode ist problematischer. Wir haben uns letztendlich für die zweite Methode entschieden. Zusammenfassen Nachdem ich so viel gesagt habe, möchte ich eine kurze Zusammenfassung machen. Bei der Behebung von Deadlock-Problemen reicht es manchmal nicht aus, nur das Deadlock-Protokoll zu betrachten, um das Problem zu lösen. Um das richtige Ergebnis zu erhalten, ist eine Analyse des gesamten Geschäftsprotokolls, des Codes und der Tabellenstruktur erforderlich. Natürlich gibt es oben einige grundlegende Kenntnisse über Datenbanksperren. Wenn Sie es nicht verstehen, können Sie meinen anderen Artikel Warum Entwickler über Datenbanksperren Bescheid wissen müssen lesen. Der letzte Artikel wurde in JGrowing-CaseStudy aufgenommen, einem umfassenden, hervorragenden Java-Lernpfad, der von der Community erstellt wurde. Wenn Sie an der Wartung von Open-Source-Projekten teilnehmen möchten, können Sie diese gemeinsam erstellen. Die GitHub-Adresse lautet: https://github.com/javagrowing/JGrowing 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:
|
<<: Zusammenfassung verschiedener Methoden für Vue zum Erreichen dynamischer Stile
>>: Tutorial zur Installation von Android Studio unter Ubuntu 19 und darunter
Inhaltsverzeichnis Vorherige Wörter Anwendungssze...
Formatkodierung 1. Bitte stellen Sie die Seitenbr...
Vorwort Das integrierte Modul von Nginx unterstüt...
Als Programmierer, der gerade Tomcat gelernt hat,...
Inhaltsverzeichnis 1. Grundlegende Konzepte 1.1 Z...
Dieser Artikel stellt ein Tutorial zur Verwendung...
Vorwort Heute entschied sich ein Kollege nach der...
Heute ist der 618. und alle großen Einkaufszentre...
Inhaltsverzeichnis 1. Objektmethoden definieren 2...
CSS3-Mustergalerie Diese CSS3-Musterbibliothek ze...
In den letzten Jahren habe ich zwischen Automatis...
Als ich das erste Mal anfing, fand ich viele Fehl...
CSS3Bitte Schauen Sie sich diese Website selbst a...
Inhaltsverzeichnis 1. Geltungsbereich 2. Funktion...
Vor ein paar Tagen habe ich mir ein Video von ein...