Ich führe gleichzeitig Postgres-Abfragen wie folgt aus:
UPDATE foo SET bar = bar + 1 WHERE baz = 1234
Jede Abfrage wirkt sich auf die feste K-Anzahl von Zeilen aus, und ich kann keine Möglichkeit finden, die Reihenfolge zu erzwingen, in der die Zeilen aktualisiert werden. Am Ende habe ich Deadlocks. Derzeit behebe ich das Problem, indem ich die Reihenfolge von Hand erzwinge. Dies bedeutet jedoch, dass ich viel mehr Abfragen ausführen muss als normalerweise, während gleichzeitig die Suchkomplexität von O (log N + K) auf O (K log N) erhöht wird.
Gibt es eine Möglichkeit, die Leistung zu verbessern, ohne anfällig für Deadlocks zu werden? Ich vermute, dass das Ersetzen des (baz)
Index durch den (baz, id)
Index funktionieren könnte, vorausgesetzt, Postgres aktualisiert die Zeilen in derselben Reihenfolge, in der sie gescannt wurden. Ist dies ein Ansatz, den es sich zu verfolgen lohnt?
quelle
CREATE TABLE
Code hinzu.Antworten:
Es gibt keine
ORDER BY
in einemSQL UPDATE
Befehl. Postgres aktualisiert die Zeilen in beliebiger Reihenfolge:Um Deadlocks mit absoluter Sicherheit zu vermeiden, können Sie Ihre Anweisungen in serialisierbarer Transaktionsisolation ausführen . Dies ist jedoch teurer und Sie müssen sich darauf vorbereiten, Befehle bei Serialisierungsfehlern zu wiederholen.
Ihre beste Vorgehensweise besteht wahrscheinlich darin,
SELECT ... ORDER BY ... FOR UPDATE
eine Unterabfrage oder eine eigenständigeSELECT
Transaktion explizit zu sperren - in der Standardisolationsstufe "Festgeschrieben lesen". Zitat von Tom Lane auf pgsql-general :Dies sollte den Job machen:
Ein mehrspaltiger Index für ist
(baz, bar)
möglicherweise perfekt für die Leistung. Aber dabar
offensichtlich viel aktualisiert wird , könnte ein einspaltiger Index für gerade(baz)
noch besser sein. Hängt von einigen Faktoren ab. Wie viele Zeilen probaz
? Sind HOT-Updates ohne den mehrspaltigen Index möglich? ...Wenn
baz
gleichzeitig aktualisiert wird, gibt es noch eine unwahrscheinliche Ecke Fall Chance für Konflikte (pro Dokumentation) :Auch, wenn Sie eine eindeutige Einschränkung beteiligt haben sollen
bar
, sollten Sie eineDEFERRABLE
Einschränkung eindeutige Verletzungen innerhalb des gleichen Befehls zu vermeiden. Verwandte Antwort:quelle
id
stattdessen nach oder nach einer anderen eindeutigen Spalte bestellebar
, sollte es keinen Eckfall oder Performance-Hit geben, oder?