Retraso de replicación / replicación detenida
El standby/la réplica se está quedando atrás respecto al primario, o la replicación se ha detenido por completo. Este árbol acota paso a paso el tipo de retraso (creciente, constante o detenido) hasta llegar a la causa raíz, como un error de aplicación, un cuello de botella de un solo hilo, un conflicto de recuperación o corrupción.
¿Cómo se comporta el retraso?
Mida primero la situación. Mire el flujo de la réplica y la métrica de retraso: ¿el retraso crece con el tiempo, está estancado en un nivel constante o la aplicación se ha detenido por completo? Esto divide la investigación en tres ramas 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;- La aplicación se detuvo por completo / hay un error
- El retraso sigue creciendo (no consigue ponerse al día)
- El retraso es constante pero se sospecha de una consulta larga
- Muy retrasada / parece inconsistente
¿Qué dice el error de aplicación?
Si la replicación se ha detenido, normalmente hay un error en un evento que se está aplicando. Mire el mensaje de error: ¿falta una fila/tabla en el destino, hay un conflicto de clave primaria o una caída de conexión/red?
SHOW REPLICA STATUS\G -- Last_Error, Last_SQL_Error, Replica_IO_Running, Replica_SQL_Running- Error de fila o tabla en conflicto/faltante
- Red/conexión caída, IO thread detenido
¿Por qué no consigue ponerse al día?
Si el retraso sigue creciendo, la réplica no da abasto con el ritmo de escritura del primario. ¿El cuello de botella es la aplicación en un solo hilo o el disco/IO de la réplica es lento? Mire el estado de los workers de aplicación y las esperas de IO.
SHOW REPLICA STATUS\G -- Seconds_Behind_Source and apply thread state
SELECT * FROM performance_schema.replication_applier_status_by_worker;- Aplicación en un solo hilo + carga de escritura intensa
- El disco/IO de la réplica es lento
¿Hay una consulta larga en el standby?
Una consulta larga en un standby de solo lectura puede bloquear la aplicación (recovery). En PostgreSQL, así es como surge un recovery conflict. Mire las consultas activas y los contadores de conflictos en el 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();- Sí, una consulta larga está bloqueando la aplicación
- No, no hay consulta, pero sigue retrasada
Causa raíz: error de aplicación (conflicto de datos)
La réplica está atascada en un evento que no puede aplicar: falta una fila en el destino, hay un conflicto de clave primaria o falta una tabla. Corrija la causa de la inconsistencia en lugar de saltar a ciegas.
Causa raíz: caída de conexión / red
El hilo receptor (IO/receiver) no puede conectarse al primario. Pueden ser el problema la red, la autenticación o segmentos de log acumulados/purgados.
Causa raíz: cuello de botella de aplicación en un solo hilo
Mientras el primario escribe en paralelo, la réplica aplica los cambios en una sola secuencia y no da abasto. Paralelice la aplicación.
Causa raíz: cuello de botella de IO en la réplica
El hilo de aplicación espera al disco, no a la CPU. El almacenamiento de la réplica no da abasto con el ritmo de escritura del primario.
Causa raíz: Recovery conflict en el standby
Una consulta larga de solo lectura en el standby está bloqueando la aplicación de los cambios del primario (conflicto de vacuum/bloqueo). PostgreSQL lo resuelve retrasando la aplicación o cancelando la consulta.
Causa raíz: réplica demasiado retrasada / corrupta - reconstrúyala
La réplica está demasiado retrasada para recuperarse, los logs necesarios se han eliminado o los datos son inconsistentes. El camino más seguro es reconstruirla desde un backup nuevo.