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:
-
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.
-
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).