DBAtlas · Атлас эксплуатации баз данных

Отставание / остановка репликации

Standby/реплика отстаёт от primary, или репликация полностью остановилась. Это дерево шаг за шагом сужает тип отставания (растёт, постоянное или остановка), чтобы дойти до первопричины: ошибка применения, узкое место однопоточного применения, конфликт восстановления или повреждение.

Как ведёт себя отставание?

Сначала оцените ситуацию. Посмотрите на поток реплики и метрику отставания: отставание растёт со временем, застыло на постоянном уровне или применение полностью остановилось? Это делит расследование на три основные ветки.

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;
  • Применение полностью остановлено / есть ошибка
  • Отставание продолжает расти (не может догнать)
  • Отставание постоянное, но подозревается долгий запрос
  • Сильно отстаёт / выглядит несогласованной

Что говорит ошибка применения?

Если репликация остановилась, обычно в применяемом событии есть ошибка. Посмотрите на сообщение об ошибке: на цели нет строки/таблицы, конфликт первичного ключа или обрыв соединения/сети?

SHOW REPLICA STATUS\G  -- Last_Error, Last_SQL_Error, Replica_IO_Running, Replica_SQL_Running
  • Ошибка конфликтующей/отсутствующей строки или таблицы
  • Сеть/соединение оборвалось, поток IO остановлен

Почему не может догнать?

Если отставание продолжает расти, реплика не успевает за скоростью записи на primary. Узкое место — однопоточное применение или медленный диск/IO реплики? Посмотрите на состояние рабочего процесса применения и ожидания IO.

SHOW REPLICA STATUS\G  -- Seconds_Behind_Source and apply thread state
SELECT * FROM performance_schema.replication_applier_status_by_worker;
  • Однопоточное применение + большая нагрузка на запись
  • Медленный диск/IO реплики

Есть ли долгий запрос на standby?

Долгий запрос на standby только для чтения может блокировать применение (recovery). В PostgreSQL так возникает конфликт восстановления. Посмотрите на активные запросы и счётчики конфликтов на 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();
  • Да, долгий запрос блокирует применение
  • Нет, запроса нет, но отставание всё равно есть

Первопричина: ошибка применения (конфликт данных)

Реплика застряла на событии, которое не может применить: на цели нет строки, конфликт первичного ключа или отсутствует таблица. Устраните причину несогласованности вместо слепого пропуска.

Первопричина: обрыв соединения / сети

Поток-получатель (IO/receiver) не может подключиться к primary. Проблема может быть в сети, аутентификации или накопленных/удалённых сегментах журнала.

Первопричина: узкое место однопоточного применения

Пока primary пишет параллельно, реплика применяет изменения в одной последовательности и не успевает. Распараллельте применение.

Первопричина: узкое место IO на реплике

Поток применения ждёт диск, а не CPU. Хранилище реплики не успевает за скоростью записи primary.

Первопричина: конфликт восстановления на standby

Долгий запрос только для чтения на standby блокирует применение изменений с primary (конфликт vacuum/блокировки). PostgreSQL решает это, задерживая применение или отменяя запрос.

Первопричина: реплика слишком отстала / повреждена — пересоздайте её

Реплика отстала слишком сильно для восстановления, нужные журналы удалены или данные несогласованы. Самый безопасный путь — пересоздать её из свежего бэкапа.

Открыть в DBAtlas →