Retard de réplication / réplication arrêtée
Le standby/réplica prend du retard sur le primaire, ou la réplication s'est entièrement arrêtée. Cet arbre affine étape par étape le type de retard (croissant, constant ou arrêté) pour atteindre la cause racine, comme une erreur d'application, un goulot mono-thread, un conflit de recovery ou une corruption.
Comment le retard se comporte-t-il ?
Mesurez d'abord la situation. Regardez le flux du réplica et la métrique de retard : le retard augmente-t-il avec le temps, est-il bloqué à un niveau constant, ou l'application s'est-elle complètement arrêtée ? Cela répartit l'analyse en trois branches principales.
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;- L'application s'est complètement arrêtée / il y a une erreur
- Le retard ne cesse d'augmenter (impossible de rattraper)
- Le retard est constant mais une longue requête est suspectée
- Très en retard / semble incohérent
Que dit l'erreur d'application ?
Si la réplication s'est arrêtée, il y a généralement une erreur dans un événement en cours d'application. Regardez le message d'erreur : s'agit-il d'une ligne/table absente sur la cible, d'un conflit de clé primaire, ou d'une coupure de connexion/réseau ?
SHOW REPLICA STATUS\G -- Last_Error, Last_SQL_Error, Replica_IO_Running, Replica_SQL_Running- Erreur de ligne ou de table en conflit/manquante
- Réseau/connexion coupé(e), thread IO arrêté
Pourquoi ne peut-il pas rattraper ?
Si le retard ne cesse d'augmenter, le réplica ne suit pas le rythme d'écriture du primaire. Le goulot est-il l'application mono-thread, ou le disque/l'IO du réplica est-il lent ? Regardez l'état du worker d'application et les attentes IO.
SHOW REPLICA STATUS\G -- Seconds_Behind_Source and apply thread state
SELECT * FROM performance_schema.replication_applier_status_by_worker;- Application mono-thread + forte charge d'écriture
- Le disque/l'IO du réplica est lent
Y a-t-il une longue requête sur le standby ?
Une longue requête exécutée sur un standby en lecture seule peut bloquer l'application (recovery). Dans PostgreSQL, c'est ainsi que naît un conflit de recovery. Regardez les requêtes actives et les compteurs de conflits sur le 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();- Oui, une longue requête bloque l'application
- Non, aucune requête, mais il reste en retard
Cause racine : erreur d'application (conflit de données)
Le réplica est bloqué sur un événement qu'il ne peut pas appliquer : ligne absente sur la cible, conflit de clé primaire ou table manquante. Corrigez la cause de l'incohérence au lieu de sauter aveuglément l'événement.
Cause racine : coupure de connexion / réseau
Le thread de réception (IO/receiver) ne parvient pas à se connecter au primaire. Le réseau, l'authentification ou des segments de journal accumulés/purgés peuvent être en cause.
Cause racine : goulot de l'application mono-thread
Alors que le primaire écrit en parallèle, le réplica applique les modifications en une seule séquence et ne suit pas. Parallélisez l'application.
Cause racine : goulot IO du réplica
Le thread d'application attend le disque, pas le CPU. Le stockage du réplica ne suit pas le rythme d'écriture du primaire.
Cause racine : conflit de recovery sur le standby
Une longue requête en lecture seule sur le standby bloque l'application des modifications du primaire (conflit vacuum/verrou). PostgreSQL le résout en retardant l'application ou en annulant la requête.
Cause racine : réplica trop en retard / corrompu - reconstruisez-le
Le réplica est trop en retard pour se rétablir, les journaux nécessaires ont été supprimés, ou les données sont incohérentes. La voie la plus sûre est de le reconstruire à partir d'une sauvegarde récente.