PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie kann man Racebedingungen vermeiden, wenn man die Methode find_or_create von DBIx::Class::ResultSet verwendet?

Nein, die Dokumentation ist falsch. Die Verwendung einer Transaktion allein ist nicht Vermeiden Sie dieses Problem. Es garantiert nur, dass die gesamte Transaktion rückgängig gemacht wird, falls eine Ausnahme auftreten sollte – damit kein inkonsistenter Zustand in der Datenbank gespeichert wird.

vermeiden Bei diesem Problem müssen Sie die Tabelle sperren - innerhalb einer Transaktion, da alle Sperren am Ende einer Transaktion aufgehoben werden. Etwas wie:

BEGIN;
LOCK TABLE mytbl IN SHARE MODE;

-- do your find_or_create here

COMMIT;

Aber das ist kein Wundermittel für alles. Es kann zu einem Leistungsproblem werden, und es kann zu Deadlocks kommen (gleichzeitige Transaktionen versuchen gegenseitig, Ressourcen zu sperren, die der andere bereits gesperrt hat). PostgreSQL erkennt eine solche Bedingung und bricht alle konkurrierenden Transaktionen bis auf eine ab. Sie müssen darauf vorbereitet sein, den Vorgang bei einem Fehler zu wiederholen.

Das PostgreSQL-Handbuch über Sperren.

Wenn Sie nicht viel Parallelität haben, können Sie das Problem auch einfach ignorieren. Das Zeitfenster ist sehr klein, so dass es nur sehr selten tatsächlich passiert. Wenn Sie den doppelten Schlüsselverletzungsfehler finden, der keinen Schaden anrichtet, dann haben Sie auch dies abgedeckt.