Deadlocks beim Löschen von Zeilen durch MySQL

9

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:

  1. LÖSCHEN weniger Zeilen gleichzeitig
  2. Verwenden Sie bei unseren DELETEs einen exponentiellen Backoff, obwohl ich befürchte, dass dies angesichts unserer spezifischen Arbeitslast nicht hilft
  3. LOCK TABLES gemäß MySQL-Dokumentation . Wir könnten wahrscheinlich akzeptieren, die SELECT- und UPDATE-Anweisungen für die Dauer der Löschungen zu blockieren.
  4. Wechseln Sie zum Tabellentyp MyISAM. Wir gingen mit InnoDB, weil wir anfänglich Transaktionen auf dieser Tabelle verwendeten. Dies ist nicht mehr der Fall. Ich bin nicht genug vertraut mit den Besonderheiten, um zu wissen, ob dies eine praktikable Lösung ist.
  5. Vielleicht UPDATE LOW_PRIORITY verwenden. Es kann sein, dass die DELETEs die SELECTs nicht beeinflussen, nur die UPDATEs, und dies kann ausreichen.
ChrisInEdmonton 20.08.2009, 15:18
quelle

2 Antworten

4

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.

    
Quassnoi 20.08.2009, 15:57
quelle
1

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%     
David Rabinowitz 20.08.2009 15:41
quelle

Tags und Links