sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo evitar las condiciones de carrera cuando se usa el método find_or_create de DBIx::Class::ResultSet?

No, la documentación es incorrecta. Usar una transacción sola no evitar este problema. Solo garantiza que toda la transacción se deshace si se produce una excepción, de modo que no persistirá ningún estado incoherente en la base de datos.

Para evitar este problema, debe bloquear la tabla, dentro de una transacción, porque todos los bloqueos se liberan al final de una transacción. Algo como:

BEGIN;
LOCK TABLE mytbl IN SHARE MODE;

-- do your find_or_create here

COMMIT;

Pero eso no es una cura mágica para todo. Puede convertirse en un problema de rendimiento y puede haber interbloqueos (transacciones simultáneas que intentan bloquear mutuamente recursos que el otro ya ha bloqueado). PostgreSQL detectará tal condición y cancelará todas menos una de las transacciones competidoras. Debe estar preparado para volver a intentar la operación en caso de falla.

El manual de PostgreSQL sobre bloqueos.

Si no tiene mucha concurrencia, también puede ignorar el problema. El intervalo de tiempo es muy pequeño, por lo que rara vez sucede. Si detecta el error de violación de clave duplicada, que no causará ningún daño, entonces también habrá cubierto esto.