Ich habe diese Abfrage, die versucht, Zeilen in die balances
Tabelle hinzuzufügen, wenn keine entsprechende Zeile in der totals
Tabelle vorhanden ist. Die Abfrage wird in einer Transaktion ausgeführt, die die Standardisolationsstufe für PostgreSQL verwendet.Kann eine INSERT-SELECT-Abfrage den Rennbedingungen unterliegen?
INSERT INTO balances (account_id, currency, amount)
SELECT t.account_id, t.currency, 0
FROM balances AS b
RIGHT OUTER JOIN totals USING (account_id, currency) AS t
WHERE b.id IS NULL
Ich habe eine UNIQUE
Einschränkung für balances (accountId, currency)
. Ich bin besorgt, dass ich in eine Race-Condition-Situation geraten werde, die zu doppelten Schlüsselfehlern führt, wenn mehrere Sessions diese Abfrage gleichzeitig ausführen. Ich habe viele Fragen zu diesem Thema gesehen, aber alle scheinen entweder Unterabfragen, mehrere Abfragen oder pgSQL-Funktionen zu beinhalten.
Da ich keine von denen in meiner Abfrage verwende, ist es frei von Race Conditions? Wenn es nicht ist, wie kann ich es reparieren?
Ja, Sie doppelte Schlüssel Fehler erhalten können erneut zu versuchen. Aus dem gleichen Grund können Sie es erhalten, wenn zwei Sitzungen die gleiche 'insert'-Anweisung mit derselben' values'-Klausel ausführen. Die Anweisung erkennt während der Ausführung einen konsistenten Status der Datenbank. Daher werden keine neuen Zeilen angezeigt, selbst wenn sie während der Ausführung der Anweisung festgeschrieben wurden. –
Eine Plpgsql-Funktion, die im Falle einer doppelten Schlüsselverletzung eine Schleife bildet, kann mit der Race-Bedingung auf der Serverseite und bei der Standard-Isolationsstufe umgehen, die * sicher * und typischerweise * das billigste * ist. Die App muss sich nicht mit Wiederholungen befassen: http://stackoverflow.com/questions/15939902/is-select-or-insert-in-a-function-prone-to-race-conditions/15950324#15950324 –