Jedną z prostych sztuczek, która może pomóc w przypadku większości zakleszczeń, jest sortowanie operacji w określonej kolejności.
Otrzymujesz impas, gdy dwie transakcje próbują zablokować dwie blokady przy przeciwnych zleceniach, tj.:
- połączenie 1:klucz blokady (1), klucz blokady (2);
- połączenie 2:klucz blokady (2), klucz blokady (1);
Jeśli oba działają w tym samym czasie, połączenie 1 zablokuje klawisz (1), połączenie 2 zablokuje klawisz (2), a każde połączenie będzie czekało, aż drugie zwolni klawisz -> zakleszczenie.
Teraz, jeśli zmieniłeś swoje zapytania tak, że połączenia będą blokować klucze w tej samej kolejności, tj.:
- połączenie 1:klucz blokady (1), klucz blokady (2);
- połączenie 2:klucz blokady (1 ), klucz blokujący (2 );
niemożliwe będzie osiągnięcie impasu.
Oto co sugeruję:
-
Upewnij się, że nie masz żadnych innych zapytań, które blokują dostęp do więcej niż jednego klucza naraz, z wyjątkiem instrukcji delete. jeśli tak (i podejrzewam, że tak), uporządkuj ich WHERE in (k1,k2,..kn) w kolejności rosnącej.
-
Popraw instrukcję usuwania, aby działała w kolejności rosnącej:
Zmień
DELETE FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
Do
DELETE FROM onlineusers
WHERE id IN (
SELECT id FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
ORDER BY id
) u;
Inną rzeczą, o której należy pamiętać, jest to, że dokumentacja MySQL sugeruje, że w przypadku zakleszczenia klient powinien automatycznie ponowić próbę. możesz dodać tę logikę do kodu klienta. (Powiedz, 3 ponowienie tego konkretnego błędu przed poddaniem się).