PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Cohérence dans postgresql avec verrouillage et sélection pour mise à jour

BEGIN; 
LOCK TABLE slots IN ACCESS EXCLUSIVE MODE; 
UPDATE slots SET job_name = '111' WHERE id IN (SELECT id FROM slots WHERE job_name IS NULL LIMIT 1) RETURNING *;
COMMIT;

Cela semble fonctionner dans Read Committed. Il s'agit uniquement de sql (identique à votre code) et peut être exécuté en un seul appel (plus rapide).

@Seth Robertson :Ce n'est pas sûr sans LOCK TABLE et sans boucle while.

S'il y a une transaction A et une transaction B en même temps :A sélectionnera la première ligne et B sélectionnera la première ligne. A verrouille et met à jour la ligne, B doit attendre que A s'engage. Ensuite, B revérifiera la condition job_name IS NULL. C'est faux et B ne mettra pas à jour - B ne sélectionnera pas la ligne suivante mais revérifiera seulement et renverra un résultat vide.

@joegester :SELECT FOR UPDATE n'est pas le problème car toutes les tables sont verrouillées.

Peut-être existe-t-il une autre façon de faire le travail - si vous supprimez et insérez des lignes (dans une autre table?) Au lieu de définir NULL. Mais je ne sais pas comment.