Wir haben eine (derzeit InnoDB) Tabelle, die ungefähr 500.000 Zeilen enthält. Dies stellt eine Warteschlange mit auszuführenden Aufgaben dar. Es ist in einer MySQL-Datenbank gespeichert.
Eine kontinuierliche Basis, mindestens einmal pro Sekunde, aber manchmal häufiger, wählen wir Daten aus und aktualisieren anschließend einige Zeilen. Einmal am Tag schneiden wir alte Reihen vom Tisch ab.
Wir haben damit begonnen, Deadlocks auf den Tisch zu bekommen, und das brachte unsere Aufgabenbearbeitung zum Stillstand. Diese Deadlocks wurden während des nächtlichen Backpfades verursacht. Die Kombination von DELETE, SELECT und UPDATE bedeutete, dass im Wesentlichen nichts produktives passieren konnte. Ich habe leider nicht die Ausgabe eines SHOW ENGINE INNODB STATUS.
Ich würde gerne die beste Option kennen, um damit umzugehen. Beachten Sie, dass unser Code Deadlocks erkennt und die Abfrage erneut ausgibt. Außerdem haben wir vor langer Zeit festgestellt, dass das Löschen aller übereinstimmenden Zeilen auf einmal für eine Datenbanktabelle, die viel Aktivität aufwies, zu anstrengend ist. Daher limitieren wir unsere Löschungen auf 10.000 Zeilen gleichzeitig und führen die Abfrage erneut aus, bis alle erforderlichen Zeilen vorhanden sind beschnitten.
Ich sehe die folgenden Optionen und möchte Meinungen dazu, welche die besten sind, oder Vorschläge für andere Optionen:
Beim Ausführen von DML
-Operationen sperrt InnoDB
alle Zeilen, die gescannt wurden und nicht übereinstimmen.
Betrachten Sie dieses Tabellenlayout:
%Vor% In diesem Fall wählt MySQL
RANGE
access path auf id
, was es günstiger findet als REF
auf data
.
In einer gleichzeitigen Transaktion können Sie die Zeilen 6
, 7
, 8
, nicht aber die Zeilen 1
bis 5
löschen oder aktualisieren, da sie gesperrt sind (trotz der Tatsache, dass nur die Zeile 2
war betroffen).
Wenn Sie id <= 5
aus der obigen Bedingung entfernen, können Sie jede Zeile außer der Zeile 3
löschen.
Leider können Sie MySQL
Zugriffspfade in DML
operations nicht kontrollieren.
Sie können Ihre Bedingungen am besten indizieren und hoffen, dass MySQL
diese Indizes auswählt.
Stellen Sie sicher, dass Ihre Transaktionsisolation als Read Committed und nicht als Repeatable Read markiert ist. Read Committed sollte der Standard sein, aber wir haben gesehen, dass in unserem Server der Innodb-Standard wiederholbar gelesen wurde.
Sie können dies überprüfen, indem Sie Folgendes ausführen:
%Vor%Um dies festzulegen, geben Sie in Ihrer my.cnf-Datei die folgende Zeile ein:
%Vor%