2017-09-15 4 views
0

Ich habe eine mysql (eigentlich MariaDB 5.5.52) Datenbank grob wie folgt beschrieben:Wie wird ein zusammengesetzter Index angeordnet, um Deadlocks zu verhindern?

CREATE TABLE table1 (
    id INT NOT NULL AUTOINCREMENT, 
    col1 INT, 
    col2 VARCHAR(32), 
    col3 VARCAHR(128), 
    PRIMARY KEY (ID), 
    UNIQUE KEY index1 (col1, col2, col3) 
); 

Es gibt mehr Spalten sind, aber alle sind in der UNIQUE Schlüssel, und es gibt keine anderen Tasten in der Tabelle.

Ich führe mehrere Threads eines Python-Skript, das in diese Datenbank einfügt. Jeder Thread tut um 100-1000 Inserts mit mysql.connector des executemany wie

ins_string = "INSERT IGNORE INTO table1 ({0}) VALUES ({1});" 
cursor.executemany(ins_string.format(fields, string_symbols), values) 

Ich laufe in Einklang Deadlock Probleme. Ich nehme an, dass diese Probleme verursacht werden, weil jeder Thread zwischen Zeilen von table1 in irgendeiner halb zufälligen Reihenfolge basierend auf der Reihenfolge festlegt, in der meine Python-Liste values generiert wird. Dies wird durch Tests bestätigt. Wenn ich eine neue Datenbank von Grund auf mit 24 Threads baue, ist die Deadlock-Rate pro executemany()-Anweisung> 80%, aber zu der Zeit, da es eine Million + Zeilen in der Datenbank gibt, ist die Deadlock-Rate nahe Null.

Ich hatte die Möglichkeit in Betracht gezogen, dass der Deadlock ein Ergebnis von Threads ist, die um AUTOINCREMENT konkurrieren, aber im standardmäßigen InnoDB 'konsekutiven' Sperrmodus scheint dies nicht so zu sein. Jeder Thread soll bis zum Ende des INSERT einen table level lock bekommen. Die Art und Weise, wie die AUTOINCREMENT- und INSERT-Schlösser interagieren, ist für mich jedoch verwirrend. Wenn ich das falsch verstanden habe, lassen Sie es mich bitte wissen.

Wenn also das Problem durch die zufällige Anordnung des eindeutigen Schlüssels verursacht wird, muss ich die insert-Anweisungen in python ordnen, bevor ich sie an MySql weitergebe. Der Index wird in irgendeiner Weise von MySql gehasht und dann geordnet. Wie kann ich das Hashing/Ordering in Python replizieren?

Ich frage nach einer Lösung für meine Diagnose des Problems hier, aber wenn Sie sehen, dass meine Diagnose falsch ist, lassen Sie es mich bitte wissen.

Antwort

0

Warum haben ID, seit Sie einen Schlüssel UNIQUE haben, der zu PRIMARY befördert werden könnte?

Unabhängig davon, sortieren Sie die Bulk-Zeile auf (col1, col2, col3) vor dem Erstellen der executemany.

Wenn das nicht ausreicht, verringern Sie die Anzahl der Zeilen in jedem executemany. 100 Reihen werden innerhalb von etwa 10% der theoretischen Bestnote erreicht. Wenn 100 die Häufigkeit von Deadlocks unter, sagen wir 10%, verringert, dann sind Sie wahrscheinlich sehr nah an der optimalen Balance zwischen der Geschwindigkeit des Massenladens und der Verlangsamung aufgrund der Wiedergabe von Deadlocks.

Wie viele CPU-Kerne haben Sie?

Gibt es andere Indizes, die Sie uns nicht zeigen? AlleUNIQUE Index Faktoren in dieses Problem. Nicht eindeutige Indizes sind kein Problem. Bitte geben Sie die vollständige SHOW CREATE TABLE.

+0

Es gibt acht Spalten, die alle im UNIQUE-Index stehen; andernfalls ist dies die vollständige Anweisung "CREATE TABLE". Die ID-Spalte existiert als Fremdschlüssel für eine Vielzahl von Untertabellen. Ich laufe nie mehr Threads als ich CPU-Cores, in der Regel bin ich auf 48-Core-Servern bei der Beschränkung auf 24 Threads oder weniger (es gibt andere Prozesse, die auch läuft). – kingledion

+0

@kingledion - OK; diese Antworten scheinen vernünftig. Also, stimme ich für (1) Vorsortierung der Zeilen für Executemany und (2) kleinere Chargen.Weniger als 24 Threads können dazu beitragen, Deadlocks etwas zu vermeiden, aber weniger Arbeit erledigen - können nicht vorhersagen, ob es sich lohnt. Welche Version von MySQL? Alte Versionen waren bei 24 Threads ineffizient. –

+0

Es ist MariaDB 5.5.52. Ich sollte wohl erwähnen, dass es MariaDB ist ... Was macht eine "alte" Version aus? – kingledion

Verwandte Themen