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

Comment éviter les conditions de concurrence lors de l'utilisation de la méthode find_or_create de DBIx::Class::ResultSet ?

Non, la documentation est incorrecte. L'utilisation d'une transaction seule ne fait pas éviter ce problème. Il garantit uniquement que l'intégralité de la transaction est annulée si une exception se produit - afin qu'aucun état incohérent ne soit conservé dans la base de données.

À éviter ce problème, vous devez verrouiller la table - à l'intérieur d'une transaction, car tous les verrous sont libérés à la fin d'une transaction. Quelque chose comme :

BEGIN;
LOCK TABLE mytbl IN SHARE MODE;

-- do your find_or_create here

COMMIT;

Mais ce n'est pas un remède magique à tout. Cela peut devenir un problème de performances et il peut y avoir des impasses (transactions simultanées essayant mutuellement de verrouiller des ressources que l'autre a déjà verrouillées). PostgreSQL détectera une telle condition et annulera toutes les transactions concurrentes sauf une. Vous devez être prêt à réessayer l'opération en cas d'échec.

Le manuel PostgreSQL sur les verrous.

Si vous n'avez pas beaucoup de simultanéité, vous pouvez également ignorer le problème. Le créneau horaire est très petit, donc cela ne se produit que très rarement. Si vous détectez l'erreur de violation de clé en double, qui ne fera aucun mal, alors vous avez également couvert cela.