Une astuce simple qui peut aider avec la plupart des blocages consiste à trier les opérations dans un ordre spécifique.
Vous obtenez un interblocage lorsque deux transactions tentent de verrouiller deux verrous à des ordres opposés, c'est-à-dire :
- connexion 1 :verrouille la clé(1), verrouille la clé(2) ;
- connexion 2 :verrouille la clé (2), verrouille la clé (1) ;
Si les deux s'exécutent en même temps, la connexion 1 verrouillera la clé (1), la connexion 2 verrouillera la clé (2) et chaque connexion attendra que l'autre libère la clé -> blocage.
Maintenant, si vous modifiez vos requêtes de sorte que les connexions verrouillent les clés dans le même ordre, c'est-à-dire :
- connexion 1 :verrouille la clé(1), verrouille la clé(2) ;
- connexion 2 : verrouille la clé (1 ), verrouille la clé (2 );
il sera impossible d'obtenir une impasse.
Voici donc ce que je propose :
-
Assurez-vous qu'aucune autre requête ne verrouille l'accès à plusieurs clés à la fois, à l'exception de l'instruction de suppression. si vous le faites (et je suppose que vous le faites), classez leur WHERE en (k1,k2,..kn) par ordre croissant.
-
Corrigez votre instruction de suppression pour qu'elle fonctionne par ordre croissant :
Modifier
DELETE FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
À
DELETE FROM onlineusers
WHERE id IN (
SELECT id FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
ORDER BY id
) u;
Une autre chose à garder à l'esprit est que la documentation MySQL suggère qu'en cas d'impasse, le client doit réessayer automatiquement. vous pouvez ajouter cette logique à votre code client. (Disons, 3 tentatives sur cette erreur particulière avant d'abandonner).