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

Verrous consultatifs ou NOWAIT pour éviter d'attendre les lignes verrouillées ?

FOR UPDATE NOWAIT n'est une bonne idée que si vous insistez pour verrouiller une ligne particulière, ce qui n'est pas De quoi as-tu besoin. Vous voulez juste tout qualification, ligne disponible (déverrouillée). La différence importante est la suivante (en citant le manuel de Postgres 9.4) :

Avec NOWAIT , l'instruction signale une erreur, plutôt que d'attendre, si une ligne sélectionnée ne peut pas être verrouillée immédiatement.

Des requêtes identiques essaieront très probablement de verrouiller le même choix arbitraire. FOR UPDATE NOWAIT va simplement renflouer avec une exception (qui annulera toute la transaction à moins que vous n'interceptiez l'erreur) et vous devez réessayer.

La solution dans ma réponse référencée sur dba.SE utilise une combinaison de FOR UPDATE en combinaison avec pg_try_advisory_lock() :

pg_try_advisory_lock est similaire à pg_advisory_lock , sauf que la fonction n'attendra pas que le verrou soit disponible. Il obtiendra soit le verrou immédiatement et renverra vrai, ou renverra faux si le verrou ne peut pas être acquis immédiatement.

Donc, votre meilleure option est ... la troisième alternative :le nouveau FOR UPDATE SKIP LOCKED dans Postgres 9.5, qui implémente le même comportement sans appel de fonction supplémentaire.

Le manuel de Postgres 9.5 compare les deux options, expliquant davantage la différence :

Pour empêcher l'opération d'attendre que d'autres transactions soient validées, utilisez soit le NOWAIT ou SKIP LOCKED option. Avec NOWAIT , l'instruction signale une erreur, plutôt que d'attendre, si une ligne sélectionnée ne peut pas être verrouillée immédiatement. Avec SKIP LOCKED , toutes les lignes sélectionnées qui ne peuvent pas être verrouillées immédiatement sont ignorées.

Sur Postgres 9.4 ou une version antérieure, votre prochaine meilleure option est d'utiliser pg_try_advisory_xact_lock(id) en combinaison avec FOR UPDATE comme démontré dans la réponse référencée :

  • MISE À JOUR Postgres… LIMITER 1

(Aussi avec une implémentation avec FOR UPDATE SKIP LOCKED .)

De côté

À proprement parler, vous obtenez des choix arbitraires, pas vraiment aléatoires. Cela peut être une distinction importante.
Une version vérifiée de votre requête se trouve dans ma réponse à votre autre question.