yo. le probleme c le `SELECT ... FOR UPDATE` apres un `UPDATE`. l'update prend deja un row exclusive lock. le select for update essaie de prendre un share lock sur la meme ligne. si deux transactions font ça en parallelle sur des lignes differentes mais avec des timings qui s'entrecroisent boom deadlock
ah donc c'est le double lock sur la meme row. mais pourquoi le `SELECT FOR UPDATE` si l'update a deja locké la ligne ?
le select for update sert a s'assurer que tu vois la version la plus recente de la ligne et que tu as le controle exclusif. mais apres un update c'est redondant. l'update a deja verrouille la ligne. t'as pas besoin de re-locker.
donc le `SELECT FOR UPDATE` apres l'update est inutile et cause le deadlock. si j'enleve le `SELECT FOR UPDATE` ca resout le probleme ?
oui exactement. l'update prend un verrou row exclusive. aucun autre update ou select for update ne pourra toucher cette ligne tant que ta transaction est active. donc si tu veux juste lire la ligne apres la modif ton `update` est suffisant.
ok je vois. mais si je fais `SELECT * FROM users WHERE id = ...` juste apres l'update sans le `FOR UPDATE` est-ce que je suis sur de voir les changements que je viens de faire ? c'est bien la meme transaction.
dans la meme transaction oui tu verras toujours tes propres modifications. c'est le comportement normal des transactions isolees. donc pas besoin de `FOR UPDATE` pour ca.
merci beaucoup. je vais tester ça en production. c'est logique maintenant que tu l'expliques. mais c'est pas super intuitif de base.
ouais c'est un piege classique avec les verrous. pour info tu peux debug les deadlocks avec `pg_locks` et en regardant le `log_lock_waits` et `deadlock_timeout` dans ta config postgres.
j'avais deja activé `log_lock_waits` mais les logs sont un peu cryptiques des fois. le message 'deadlock detected' est clair mais la cause l'etait moins.
apres si t'as une logique qui depend de l'ordre des `UPDATE` sur des lignes differentes ca peut etre plus complexe. mais pour un simple update-read sur la meme ligne c'est le `FOR UPDATE` qui gene.
non la logique est simple on met a jour un champ et on veut relire les infos pour confirmer. donc j'enleve le `FOR UPDATE`. merci encore pour ton aide precieuse.
pas de probleme. pense a monitorer apres le deploy si les deadlocks disparaissent bien.
je ferai ça. a priori ca devrait etre bon. thx.
Vous devez être connecté pour poster un message !
Recevoir les derniers articles gratuitement en créant un compte !
S'inscrire
edith-caron
Membre depuis le 03/09/2024actif
salut a tous. on a des deadlocks reguliers sur une base postgres 14.5. c'est sur une table toute simple `users` avec un id et un nom. la requete c'est un `UPDATE users SET name = '...' WHERE id = ...` suivi d'un `SELECT ... FOR UPDATE`. ca arrive sous forte charge. je pige pas pourquoi.
des pistes ?