PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come evitare le condizioni di gara quando si utilizza il metodo find_or_create di DBIX::Class::ResultSet?

No, la documentazione non è corretta. L'utilizzo di una sola transazione non evitare questo problema. Garantisce solo il rollback dell'intera transazione se si verifica un'eccezione, in modo che nessuno stato incoerente venga mantenuto nel database.

Per evitare questo problema è necessario bloccare la tabella - all'interno di una transazione, perché tutti i blocchi vengono rilasciati alla fine di una transazione. Qualcosa come:

BEGIN;
LOCK TABLE mytbl IN SHARE MODE;

-- do your find_or_create here

COMMIT;

Ma non è una cura magica per tutto. Può diventare un problema di prestazioni e potrebbero esserci deadlock (transazioni simultanee che cercano reciprocamente di bloccare le risorse che l'altro ha già bloccato). PostgreSQL rileverà tale condizione e cancellerà tutte le transazioni concorrenti tranne una. Devi essere pronto a ritentare l'operazione in caso di errore.

Il manuale di PostgreSQL sui blocchi.

Se non hai molta concorrenza, potresti anche ignorare il problema. La fascia oraria è molto piccola, quindi accade solo molto raramente. Se rilevi l'errore di violazione della chiave duplicata, che non danneggerà, hai coperto anche questo.