Deadlock postgres recurrent avec requete simple

Posté par edith-caron le 10/12/2025
RÉSOLU

edith-caron

Membre depuis le 03/09/2024

actif

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.

BEGIN;
UPDATE users SET name = 'new_name' WHERE id = 123;
SELECT * FROM users WHERE id = 123 FOR UPDATE;
COMMIT;

des pistes ?

Commentaires

thibault-coste

Membre depuis le 13/04/2019

actif secouriste

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

edith-caron

Membre depuis le 03/09/2024

actif

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 ?

thibault-coste

Membre depuis le 13/04/2019

actif secouriste

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.

edith-caron

Membre depuis le 03/09/2024

actif

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 ?

thibault-coste

Membre depuis le 13/04/2019

actif secouriste

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.

edith-caron

Membre depuis le 03/09/2024

actif

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.

thibault-coste

Membre depuis le 13/04/2019

actif secouriste

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.

edith-caron

Membre depuis le 03/09/2024

actif

merci beaucoup. je vais tester ça en production. c'est logique maintenant que tu l'expliques. mais c'est pas super intuitif de base.

thibault-coste

Membre depuis le 13/04/2019

actif secouriste

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.

edith-caron

Membre depuis le 03/09/2024

actif

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.

thibault-coste

Membre depuis le 13/04/2019

actif secouriste

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.

edith-caron

Membre depuis le 03/09/2024

actif

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.

thibault-coste

Membre depuis le 13/04/2019

actif secouriste

pas de probleme. pense a monitorer apres le deploy si les deadlocks disparaissent bien.

edith-caron

Membre depuis le 03/09/2024

actif

je ferai ça. a priori ca devrait etre bon. thx.

Laisser une réponse

Vous devez être connecté pour poster un message !

Rejoindre la communauté

Recevoir les derniers articles gratuitement en créant un compte !

S'inscrire