linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it worksскоро
  • Уроки
  • База знаний
  • Собеседование
home/postgres/kb/Репликация/hot-standby-feedback

kb/replication ── Репликация ── advanced

hot_standby_feedback и vacuum мастера

Длинный запрос на standby читает старые версии строк. Если primary их уже почистил vacuum'ом, standby обязан либо отменить запрос (конфликт восстановления), либо отстать. hot_standby_feedback = on говорит primary не удалять то, что ещё нужно standby - ценой роста мусора на primary.

view as markdownaka: standby-feedback, recovery-conflict

Откуда конфликт

Standby проигрывает WAL primary, в том числе записи vacuum'а: «эти мёртвые версии удалены, страница ужата». Но на standby в этот момент может идти долгий SELECT, которому те самые версии ещё видны по его снимку.

Получается тупик. Standby не может и проиграть запись очистки (она выдернет строки из-под живого запроса), и бесконечно её откладывать (тогда лаг растёт без предела). PostgreSQL выбирает: подождать max_standby_streaming_delay, и если запрос не закончился - отменить его. В логе standby это «canceling statement due to conflict with recovery», код ошибки 40001.

Что делает feedback

hot_standby_feedback = on (на standby) разворачивает поток информации назад. Standby сообщает primary свой самый старый нужный xmin - границу, ниже которой удалять версии нельзя, потому что их читает запрос на реплике.

Primary получает этот xmin и сдвигает свой горизонт очистки (см. transaction-horizon) так, чтобы не трогать ещё нужное standby. Конфликты восстановления исчезают: vacuum на primary просто не доходит до тех версий.

Чем платим

Тем же, чем за любую долгую транзакцию. Удерживая горизонт ради запроса на standby, primary не может почистить мёртвые версии в горячих таблицах. Растёт bloat, autovacuum ходит вхолостую, n_dead_tup копится. Один забытый аналитический запрос на реплике может раздуть таблицу на primary так же, как idle in transaction на самом primary.

sql
-- на primary: чей backend_xmin держит горизонт
SELECT pid, backend_xmin, state, query
FROM pg_stat_activity
WHERE backend_xmin IS NOT NULL
ORDER BY age(backend_xmin) DESC;
-- xmin, пришедший от standby, виден в строке walsender:
SELECT application_name, backend_xmin FROM pg_stat_replication;

Когда что включать

  • Реплика для отчётов с долгими запросами - часто feedback = on, чтобы запросы не отменялись. Следи за bloat на primary.
  • Реплика-горячий-резерв (failover, без чтения) - feedback = off, primary чистит свободно, отменять нечего.
  • Компромисс без feedback - поднять max_standby_streaming_delay, разрешив standby отставать на время долгого запроса, не трогая primary.

Это прямое следствие того, что vacuum (см. vacuum) привязан к горизонту транзакций. Кто держит снимок (на primary или на standby с feedback), тот держит мусор. См. streaming-replication про сам поток WAL.

§ команды

bash
SHOW hot_standby_feedback;

Проверить, шлёт ли standby свой xmin обратно на primary

bash
SELECT application_name, backend_xmin FROM pg_stat_replication;

На primary: какой xmin удерживает каждый standby с feedback

bash
SHOW max_standby_streaming_delay;

Сколько standby ждёт перед отменой запроса при конфликте восстановления

§ см. также

  • streaming-replicationФизическая (потоковая) репликацияStandby проигрывает у себя тот же WAL, что пишет primary, и получается побайтовая копия кластера. Primary отдаёт журнал процессом walsender, standby принимает walreceiver'ом и применяет startup-процессом. Лаг меряется в LSN: насколько replay на standby отстал от записи на primary.
  • logical-replicationЛогическая репликация (publication/subscription)Логическая репликация шлёт не байты WAL, а декодированные изменения строк: INSERT/UPDATE/DELETE по конкретным таблицам. Источник объявляет PUBLICATION, приёмник создаёт SUBSCRIPTION. Требует wal_level = logical. Можно реплицировать часть таблиц между разными версиями и схемами.
  • transaction-horizonГоризонт транзакцииГоризонт - минимум backend_xmin по всем активным транзакциям. Версию строки можно убрать, только если она стала мёртвой раньше горизонта. Одна долгая или idle-in-transaction транзакция отодвигает горизонт назад и запрещает уборку мусора во всей базе.
  • vacuumVACUUM и removable cutoffVACUUM удаляет мёртвые версии из таблицы и индексов, обновляет Free Space Map и Visibility Map, продвигает горизонт заморозки. Удаляет только версии старше removable cutoff. Обычный VACUUM не уменьшает файл - это делает VACUUM FULL под эксклюзивной блокировкой.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки