Replikationsverzögerung / gestoppt
Die Standby/Replica fällt hinter den Primary zurück, oder die Replikation ist ganz gestoppt. Dieser Baum grenzt die Art der Verzögerung Schritt für Schritt ein (wachsend, konstant oder gestoppt), um zur Ursache zu gelangen, etwa einem Apply-Fehler, einem Single-Thread-Engpass, einem Recovery-Konflikt oder Korruption.
Wie verhält sich die Verzögerung?
Miss zuerst die Lage. Betrachte den Replica-Stream und die Verzögerungsmetrik: Wächst die Verzögerung mit der Zeit, bleibt sie auf konstantem Niveau, oder ist das Apply ganz gestoppt? Das teilt die Untersuchung in drei Hauptzweige.
SELECT client_addr, state, write_lag, flush_lag, replay_lag,
pg_wal_lsn_diff(sent_lsn, replay_lsn) AS bytes_behind
FROM pg_stat_replication;- Apply ganz gestoppt / es gibt einen Fehler
- Verzögerung wächst weiter (kann nicht aufholen)
- Verzögerung ist konstant, aber eine lange Abfrage steht im Verdacht
- Weit zurück / wirkt inkonsistent
Was sagt der Apply-Fehler?
Ist die Replikation gestoppt, gibt es meist einen Fehler in einem angewendeten Event. Sieh dir die Fehlermeldung an: Fehlt eine Zeile/Tabelle auf dem Ziel, gibt es einen Primary-Key-Konflikt oder einen Verbindungs-/Netzwerkabbruch?
SHOW REPLICA STATUS\G -- Last_Error, Last_SQL_Error, Replica_IO_Running, Replica_SQL_Running- Fehler wegen kollidierender/fehlender Zeile oder Tabelle
- Netzwerk/Verbindung abgebrochen, IO-Thread gestoppt
Warum kann sie nicht aufholen?
Wächst die Verzögerung weiter, kommt die Replica mit der Schreibrate des Primary nicht mit. Ist das Single-Thread-Apply der Engpass, oder ist die Platte/IO der Replica langsam? Betrachte Zustand des Apply Workers und IO-Waits.
SHOW REPLICA STATUS\G -- Seconds_Behind_Source and apply thread state
SELECT * FROM performance_schema.replication_applier_status_by_worker;- Single-Thread-Apply + hohe Schreiblast
- Die Platte/IO der Replica ist langsam
Gibt es eine lange Abfrage auf der Standby?
Eine lange Abfrage auf einer schreibgeschützten Standby kann das Apply (Recovery) blockieren. In PostgreSQL entsteht so ein Recovery-Konflikt. Betrachte aktive Abfragen und Konfliktzähler auf der Standby.
SELECT now()-query_start AS dur, pid, state, query
FROM pg_stat_activity WHERE state='active' ORDER BY query_start;
SELECT confl_snapshot, confl_lock, confl_bufferpin FROM pg_stat_database_conflicts WHERE datname=current_database();- Ja, eine lange Abfrage blockiert das Apply
- Nein, keine Abfrage, aber sie liegt trotzdem zurück
Ursache: Apply-Fehler (Datenkonflikt)
Die Replica hängt an einem Event, das sie nicht anwenden kann: eine auf dem Ziel fehlende Zeile, ein Primary-Key-Konflikt oder eine fehlende Tabelle. Behebe die Ursache der Inkonsistenz, statt blind zu überspringen.
Ursache: Verbindungs- / Netzwerkabbruch
Der Empfänger-Thread (IO/receiver) kann sich nicht mit dem Primary verbinden. Das Problem können Netzwerk, Authentifizierung oder angesammelte/bereinigte Log-Segmente sein.
Ursache: Single-Thread-Apply-Engpass
Während der Primary parallel schreibt, wendet die Replica Änderungen in einer einzigen Abfolge an und kommt nicht mit. Das Apply parallelisieren.
Ursache: IO-Engpass der Replica
Der Apply-Thread wartet auf die Platte, nicht auf die CPU. Der Speicher der Replica kommt mit der Schreibrate des Primary nicht mit.
Ursache: Recovery-Konflikt auf der Standby
Eine lange Leseabfrage auf der Standby blockiert das Anwenden von Änderungen des Primary (Vacuum-/Sperrkonflikt). PostgreSQL löst das, indem es das Apply verzögert oder die Abfrage abbricht.
Ursache: Replica zu weit zurück / beschädigt - neu aufbauen
Die Replica liegt zu weit zurück, um sich zu erholen, die benötigten Logs wurden entfernt oder die Daten sind inkonsistent. Der sicherste Weg ist ein Neuaufbau aus einem frischen Backup.