PostgreSQL-Fehler: canceling statement due to conflict with recovery
FATAL: terminating connection due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.
HINT: In a moment you should be able to reconnect to the database and repeat your command.
Dieser Fehler existiert nur auf Hot-Standby-Replikas. Die Replika muss WAL vom Primary anwenden, um synchron zu bleiben; Ihre Query brauchte Zeilenversionen, die das eingehende WAL (typischerweise Vacuum-Aufräumen) entfernt. Nach dem Anhalten des Replays für max_standby_streaming_delay wählte die Replika Replikation über Ihre Query und brach sie ab.
Was dieser Fehler bedeutet
Die Replika bedient Lesevorgänge, während sie kontinuierlich das WAL des Primary wiederholt — zwei Aufgaben, die in Konflikt geraten, wenn das Replay Daten ändern oder entfernen will, die eine laufende Query noch sehen kann. PostgreSQL verzögert das Replay zuerst, um die Query beenden zu lassen (bis zu max_standby_streaming_delay, Standard 30 s), und bricht dann die Query ab. Es ist ein bewusster Kompromiss zwischen Replika-Aktualität und Query-Überleben, und jeder Regler bewegt sich nur entlang dieser Achse.
Häufige Ursachen
- Lange laufende Queries auf der Replika (Reports, Analytics), die gegen Vacuum-Aktivität auf dem Primary konkurrieren — mit Abstand der übliche Fall.
- DDL auf dem Primary: das Wiederholen eines DROP oder ALTER braucht einen Exklusiv-Lock auf der Replika, im Konflikt mit jeder Query, die das Objekt verwendet.
So diagnostizieren Sie ihn
-- Auf der Replika: Konfliktzähler nach Typ und Datenbank
SELECT * FROM pg_stat_database_conflicts;
confl_snapshot ist der Vacuum-Aufräum-Fall; confl_lock deutet auf DDL auf dem Primary hin. Korrelieren Sie mit den Arbeitslasten, die zu diesen Zeiten auf der Replika laufen.
So beheben Sie ihn
Wählen Sie den Kompromiss explizit:
hot_standby_feedback = on(auf der Replika): die Replika teilt dem Primary mit, welche Zeilenversionen sie noch braucht, und das Vacuum auf dem Primary verschont sie. Queries sterben nicht mehr; die Kosten sind Bloat auf dem Primary, der durch lange Replika-Queries zurückgehalten wird — derselbe Effekt wie bei einer lokal laufenden langen Transaktion.- Erhöhen Sie
max_standby_streaming_delayauf einer dedizierten Reporting-Replika: Queries gewinnen, die Replika hinkt während ihrer Laufzeit hinterher. In Ordnung, wenn die Replika nicht für failover-kritische Aktualität genutzt wird. - Wiederholen Sie bei SQLSTATE 40001 für kurze Queries — der HINT meint es ernst: einen Moment später gelingt dieselbe Query meist.
- Trennen Sie Arbeitslasten: eine schnelle, aktuelle Replika für App-Lesevorgänge; eine separate Replika mit großzügiger Verzögerung für Analytics.
