Deadlock-Fall 7

Quelle: öffentliches Konto Yangyidba

I. Einleitung

Deadlock ist eigentlich ein sehr interessantes und herausforderndes technisches Problem. Wahrscheinlich werden jeder DBA und einige Entwicklungsstudenten im Laufe der Arbeit darauf stoßen. In Bezug auf Deadlock werde ich weiterhin eine Reihe von Fallstudien schreiben, in der Hoffnung, Freunden zu helfen, die Deadlock verstehen wollen.

2. Fallanalyse

2.1 Geschäftsszenario

Studenten der Geschäftsentwicklung möchten Daten synchronisieren. Ihre Logik besteht darin , über den Aktualisierungsvorgang zu aktualisieren. Wenn die vom aktualisierten Datensatz zurückgegebenen affect_rows 0 sind, wird die insert-Anweisung aufgerufen, um das Einfügen zu initialisieren . Wenn das Einfügen fehlschlägt, wird der Aktualisierungsvorgang erneut ausgeführt, und bei gleichzeitigen Vorgängen mehrerer Sitzungen tritt ein Deadlock auf.

2.2 Umweltbeschreibung

Die Transaktionsisolationsstufe von MySQL 5.6.24 ist RR

create table ty (
  id int not null primary key auto_increment ,
  c1 int not null default 0,
  c2 int not null default 0,
  c3 int not null default 0,
  unique key uc1(c1),
  unique key uc2(c2)
) engine=innodb ;
insert into ty(c1,c2,c3)
values(1,3,4),(6,6,10),(9,9,14);

2.3 Testfall

2.4 Deadlock-Protokoll

2018-03-27 17:59:23 0x7f75bf39d700
*** (1) TRANSACTION:
TRANSACTION 1863, ACTIVE 76 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1
MySQL thread id 382150, OS thread handle 56640, query id 28 localhost root update
insert into ty (c1,c2,c3) values(3,4,2)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 28 page no 5 n bits 72 index uc2 of table `test`.`ty` trx id 1863 lock_mode X locks gap before rec insert intention waiting
*** (2) TRANSACTION:
TRANSACTION 1864, ACTIVE 65 sec inserting, thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 382125, OS thread handle 40032, query id 62 localhost root update
insert into ty (c1,c2,c3) values(3,4,2)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 28 page no 5 n bits 72 index uc2 of table `test`.`ty` trx id 1864 lock_mode X locks gap before rec
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 28 page no 4 n bits 72 index uc1 of table `test`.`ty` trx id 1864 lock mode S waiting
*** WE ROLL BACK TRANSACTION (2)

2.5 Analysieren Sie das Deadlock-Protokoll

Zunächst müssen wir die Sperrlogik der Einfügeoperation erneut hervorheben.

Die erste Stufe: Überprüfung der Eindeutigkeitsbeschränkung, zuerst  LOCK_S + LOCK_ORDINARY anwenden

Die zweite Stufe: Nach dem Erwerb der Sperre von Stufe 1 und dem erfolgreichen Einfügen befindet sich an der eingefügten Position eine GAP-Sperre: LOCK_INSERT_INTENTION, um andere Konflikte beim Einfügen eindeutiger Schlüssel zu verhindern.

Nachdem die neuen Daten eingefügt wurden: LOCK_X + LOCK_REC_NOT_GAP

Wenn für den Einfügevorgang ein eindeutiger Einschränkungskonflikt auftritt, müssen Sie dem in Konflikt stehenden eindeutigen Index S Next-Key Lock hinzufügen. Von hier aus werden Sie feststellen, dass es auch auf der RC-Transaktionsisolationsstufe eine Next-Key-Lock-Sperre gibt, wodurch die Parallelität blockiert wird. Was das Dokument jedoch nicht sagt, ist, dass für den eindeutigen Index, in dem der Konflikt erkannt wird, der wartende Thread den nächsten Datensatz nach Erhalt der S-Sperre sperren muss. Der Quellcode wird verwendet, um die Funktion row_ins_scan_sec_index_for_duplicate zu bestimmen.

Zweitens benötigen wir die entsperrte Kompatibilitätsmatrix.

Aus der Kompatibilitätsmatrix können wir folgende Schlussfolgerungen ziehen:

Es gibt keine Konflikte zwischen INSERT-Operationen.

GAP, Next-Key blockiert das Einfügen.

GAP und Record, Next-Key werden nicht in Konflikt geraten.

Aufzeichnen und Aufzeichnen, Next-Key-Konflikt miteinander.

Die vorhandene Einfügesperre verhindert nicht, dass Sperren hinzugefügt werden.

Bereits gehaltene GAP-Sperren blockieren die Einfügungsabsichtssperre INSERT_INTENTION.

Darüber hinaus werden GAP-Sperren angewendet, um nicht vorhandene Datensätze über einen eindeutigen Index zu aktualisieren oder zu löschen.

Analyse

Nachdem wir die oben genannten Grundkenntnisse verstanden hatten, begannen wir mit der Analyse des Deadlock-Protokolls:

T1: sess1 aktualisiert die Daten über den eindeutigen Schlüssel. Da c2 = 4 nicht vorhanden ist, ist die zurückgegebene Affektzeile 0, und MySQL gilt für die GAP-Sperre zwischen (3,6).

T2: Die Situation von sess2 ähnelt der von sess1, und die GAP-Sperre zwischen (3,6) wird ebenfalls angewendet. Aus der obigen Kompatibilitätsmatrix ergeben sich keine Konflikte zwischen den beiden GAP-Sperren.

T3: sess1 gibt die Affektzeile gemäß der Update-Anweisung als 0 zurück und führt die Einfügeoperation aus. Zu diesem Zeitpunkt muss eine Einfügungsabsichtssperre beantragt werden. Die von der Sitzung sess2 gehaltene GAP-Sperre steht in Konflikt mit der von sess1 angewendeten Einfügungsabsichtssperre, und es wird gewartet.

Index uc2 der Tabelle test.ty trx id 1863 lock_mode X sperrt die Lücke, bevor die Absicht zum Einfügen der Aufnahme abgewartet wird

T4: sess2 ähnelt sess1. Gemäß der Update-Anweisung wird die betroffene Zeile als 0 zurückgegeben und die Einfügeoperation ausgeführt. Die angewendete Einfügungsabsichtssperre steht in Konflikt mit der GAP-Sperre, die in der Aktualisierungsanweisung von sess1 enthalten ist. sess1 (Halten der GAP-Sperre), sess2 (Halten der GAP-Sperre), sess1 (Einfügungsabsichtssperre, die auf die Freigabe der GAP-Sperre von sess2 wartet) sess2 (Einfügungsabsichtssperre, die auf die Freigabe der GAP-Sperre von sess1 wartet)  bilden eine kreisförmige Wartezeit, die zu einem Deadlock führt.

2.6 Lösung

Aus der Perspektive der Verarbeitungslogik des Geschäftsszenarios muss das Unternehmen zwei Anforderungen senden, eine Aktualisierung und eine Einfügung, um die Geschäftslogik zu vervollständigen, die nicht benutzerfreundlich und optimiert ist.

Tatsächlich können wir gut mit den Klassenkameraden der Entwicklung kommunizieren, die Idempotenz des Geschäfts bestätigen, die Methode zum Einfügen bei doppeltem Schlüssel verwenden, einfügen, wenn keine vorhanden ist, aktualisieren, falls vorhanden, ein Aufruf kann die Funktion der vorherigen 2 Vorgänge vervollständigen und die Leistung verbessern.

Drei, Zusammenfassung

Abschließend möchte ich über die Idee sprechen, das Deadlock-Problem zu lösen:

1. Haben Sie solide Grundkenntnisse über Schlösser.

2. Es ist schwierig, die spezifische SQL-Ausführungssituation allein anhand des Deadlock-Protokolls zu beurteilen. Es ist erforderlich, mit den Klassenkameraden der Entwicklung zu kommunizieren, um die SQL-Logik für die Geschäftsausführung zu klären und anschließend den Test zu simulieren.

Erweitertes Lesen

Der vollständige Text ist vorbei.

Viel Spaß mit MySQL :)

Die Klasse "MySQL Core Optimization" von Lehrer Ye wurde auf MySQL 8.0 aktualisiert. Scannen Sie den Code, um die Reise von MySQL 8.0 zu beginnen

Ich denke du magst

Origin blog.csdn.net/n88Lpo/article/details/108924174
Empfohlen
Rangfolge