Ett enkelt knep som kan hjälpa till med de flesta dödlägen är att sortera operationerna i en specifik ordning.
Du får ett dödläge när två transaktioner försöker låsa två lås vid motsatta order, dvs:
- anslutning 1:låser nyckel(1), låser nyckel(2);
- anslutning 2:låser nyckel(2), låser nyckel(1);
Om båda körs samtidigt, låser anslutning 1 nyckel(1), anslutning 2 låser nyckel(2) och varje anslutning väntar på att den andra släpper nyckeln -> blockerat låsläge.
Nu, om du ändrade dina frågor så att anslutningarna skulle låsa nycklarna i samma ordning, dvs:
- anslutning 1:låser nyckel(1), låser nyckel(2);
- anslutning 2:låser nyckel (1 ), låser nyckel (2 );
det kommer att vara omöjligt att få ett dödläge.
Så det här är vad jag föreslår:
-
Se till att du inte har några andra frågor som låser åtkomst till mer än en nyckel åt gången förutom delete-satsen. om du gör det (och jag misstänker att du gör det), beställ deras WHERE i (k1,k2,..kn) i stigande ordning.
-
Åtgärda din raderingssats så att den fungerar i stigande ordning:
Ändra
DELETE FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
Till
DELETE FROM onlineusers
WHERE id IN (
SELECT id FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
ORDER BY id
) u;
En annan sak att tänka på är att MySQL-dokumentationen tyder på att klienten ska försöka igen automatiskt i händelse av ett dödläge. du kan lägga till denna logik i din klientkod. (Säg, 3 försök igen på detta specifika fel innan du ger upp).