Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie man MySQL vermeidet 'Deadlock gefunden, wenn versucht wird, eine Sperre zu erhalten; Versuchen Sie, die Transaktion neu zu starten'

Ein einfacher Trick, der bei den meisten Deadlocks helfen kann, ist das Sortieren der Operationen in einer bestimmten Reihenfolge.

Sie erhalten einen Deadlock, wenn zwei Transaktionen versuchen, zwei Sperren in entgegengesetzter Reihenfolge zu sperren, dh:

  • Verbindung 1:sperrt Schlüssel(1), sperrt Schlüssel(2);
  • Verbindung 2:sperrt Taste(2), sperrt Taste(1);

Wenn beide gleichzeitig laufen, sperrt Verbindung 1 den Schlüssel (1), Verbindung 2 sperrt den Schlüssel (2) und jede Verbindung wartet darauf, dass die andere den Schlüssel freigibt -> Deadlock.

Wenn Sie nun Ihre Abfragen so geändert haben, dass die Verbindungen die Schlüssel in derselben Reihenfolge sperren würden, dh:

  • Verbindung 1:sperrt Schlüssel(1), sperrt Schlüssel(2);
  • Verbindung 2:Schlüssel sperren (1 ), Sperrtaste (2 );

es wird unmöglich sein, einen Deadlock zu bekommen.

Also das ist, was ich vorschlage:

  1. Stellen Sie sicher, dass Sie außer der Löschanweisung keine anderen Abfragen haben, die den Zugriff auf mehr als einen Schlüssel gleichzeitig sperren. Wenn Sie dies tun (und ich vermute, dass Sie dies tun), ordnen Sie ihr WHERE in (k1, k2,..kn) in aufsteigender Reihenfolge.

  2. Korrigieren Sie Ihre Löschanweisung so, dass sie in aufsteigender Reihenfolge funktioniert:

Ändern

DELETE FROM onlineusers 
WHERE datetime <= now() - INTERVAL 900 SECOND

An

DELETE FROM onlineusers 
WHERE id IN (
    SELECT id FROM onlineusers
    WHERE datetime <= now() - INTERVAL 900 SECOND 
    ORDER BY id
) u;

Eine andere zu beachtende Sache ist, dass die MySQL-Dokumentation vorschlägt, dass der Client im Falle eines Deadlocks automatisch einen neuen Versuch starten sollte. Sie können diese Logik zu Ihrem Client-Code hinzufügen. (Angenommen, 3 Wiederholungen bei diesem bestimmten Fehler, bevor aufgegeben wird).