PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como evitar condições de corrida ao usar o método find_or_create de DBIx::Class::ResultSet?


Não, a documentação está incorreta. Usar apenas uma transação não evitar este problema. Ele apenas garante que toda a transação seja revertida se ocorrer uma exceção - para que nenhum estado inconsistente seja persistido no banco de dados.

Para evitar neste problema você deve bloquear a tabela - dentro de uma transação, pois todos os bloqueios são liberados ao final de uma transação. Algo como:
BEGIN;
LOCK TABLE mytbl IN SHARE MODE;

-- do your find_or_create here

COMMIT;

Mas isso não é uma cura mágica para tudo. Isso pode se tornar um problema de desempenho e pode haver impasses (transações simultâneas tentando bloquear recursos que o outro já bloqueou). O PostgreSQL detectará tal condição e cancelará todas as transações concorrentes, exceto uma. Você deve estar preparado para repetir a operação em caso de falha.

O manual do PostgreSQL sobre bloqueios.

Se você não tiver muita simultaneidade, também poderá ignorar o problema. O intervalo de tempo é muito pequeno, então raramente acontece. Se você detectar o erro de violação de chave duplicada, que não causará nenhum dano, você também cobriu isso.