Failover в PostgreSQL: где теряются подтверждённые данные
Резервный сервер PostgreSQL можно повысить до основного за минуты, но последние транзакции могут не сохраниться. Разбираем, когда асинхронная репликация теряет подтверждённые данные, чем помогает синхронная и как не получить два «основных» сервера.

Failover не равен сохранению всех транзакций
В PostgreSQL 17 резервный сервер может принимать поток WAL от основного и стать новым основным после аварии. Но при асинхронной репликации основной подтверждает запись клиенту, не дожидаясь, пока резервный получит и сохранит соответствующий WAL. Если основной сервер погибнет в этот промежуток, последние подтверждённые транзакции могут не попасть на новый основной.
Цена компромисса зависит от настройки: асинхронная репликация уменьшает задержку записи, синхронная позволяет ждать подтверждения от реплики, но способна остановить запись при её недоступности. Сам PostgreSQL обеспечивает механизмы репликации и продвижения сервера, но не решает за вас, когда объявлять аварию и какой узел повышать. Для этого нужна внешняя система управления или чёткая ручная процедура.
Надпись «репликация работает» не отвечает на главный вопрос: может ли выбранный резервный сервер восстановить каждую транзакцию, которую приложение уже сочло успешной?
Где возникает окно потери
Основной сервер сначала записывает изменения в журнал упреждающей записи — WAL (Write-Ahead Log)1. При потоковой репликации он отправляет записи журнала резервному серверу. Тот получает их, записывает и применяет к своей копии базы. Эти события происходят не одновременно.
При асинхронной репликации клиент может получить успешный ответ после фиксации транзакции на основном сервере, пока резервный ещё не получил нужный WAL. Если основной внезапно отключится, продвижение отстающей реплики отбросит транзакции, которых на ней нет. Их могли видеть пользователи и внешние системы, хотя новый основной о них не знает.
При штатном переключении, когда старый сервер доступен, можно остановить запись, дождаться передачи и применения WAL, а затем сменить роли. При внезапной аварии такого окна нет: оператор или автоматизация выбирает, какую реплику продвигать. Поэтому важны не только настройки репликации, но и то, насколько далеко она отстала именно в момент отказа.
Термин: RPO — допустимая потеря данных, выраженная временем или объёмом изменений. Например, требование «не терять подтверждённые транзакции» строже, чем требование восстановить базу с потерей последних секунд записей.
Асинхронная и синхронная репликация
В PostgreSQL 17 режим ожидания задаёт параметр synchronous_commit, а список синхронных реплик — synchronous_standby_names. Одного включения потоковой репликации недостаточно, чтобы подтверждение записи зависело от резервного сервера: его нужно назначить синхронным и выбрать подходящий уровень ожидания.
| Режим | Когда основной подтверждает транзакцию | Что это значит при отказе | Цена |
|---|---|---|---|
| Асинхронный | Не ждёт подтверждения реплики | Можно потерять транзакции, которых реплика не получила | Меньше задержка и меньше зависимость от доступности реплики |
synchronous_commit = on с синхронной репликой | После локальной фиксации и подтверждения, что реплика сбросила WAL на диск | Снижает риск потери подтверждённых транзакций при отказе основного | Запись ждёт реплику; её сбой может задержать или остановить фиксацию |
synchronous_commit = remote_apply | После применения изменений синхронной репликой | Реплика уже может обслуживать чтения с учётом подтверждённой транзакции | Ожидание обычно дольше: реплика должна не только сохранить WAL, но и применить его |
synchronous_commit = remote_write | После записи WAL репликой в операционную систему | Подтверждение слабее, чем ожидание сброса WAL на диск | Компромисс по задержке; не следует трактовать как гарантию устойчивого хранения на носителе |
Поведение синхронной репликации зависит от конфигурации и отказа узлов. Если задано ожидание синхронной реплики, а подходящего узла нет, фиксация транзакций, которым нужно такое подтверждение, может ждать. Это цена более строгой гарантии доступности данных. Настройка с несколькими синхронными репликами может требовать подтверждения от заданного числа узлов; конкретный режим выбирают по документации к используемым параметрам, а не по одному слову «синхронная».
Даже синхронное подтверждение не заменяет резервное копирование. Оно защищает от части сценариев отказа узла, но не от ошибочного удаления данных, повреждения логики приложения или ситуации, когда проблема затронула и основной, и реплику.
Failover: сначала безопасность, затем скорость
Критичный риск автоматического переключения — не только потерять последние записи, но и получить два сервера, которые оба принимают запись. Например, основной временно потерял связь с системой управления, но продолжает обслуживать часть приложения. Если в это время продвинуть реплику, возникнут две расходящиеся копии. Их нельзя безопасно объединить простым возвращением старого сервера в кластер.
Поэтому переключение должно включать fencing — надёжное исключение старого основного из записи: остановку процесса, выключение узла или иной механизм, который гарантирует, что он больше не обслуживает запись. Одного сетевого тайм-аута недостаточно, чтобы доказать, что старый сервер выключен. После восстановления его обычно нужно вернуть в кластер как реплику и согласовать с новой историей WAL; порядок действий зависит от инструмента оркестрации и состояния узлов.
Перед продвижением реплики процедура должна ответить на четыре вопроса:
- Старый основной действительно не может принимать записи?
- Какой резервный сервер получил больше всего WAL и подходит для продвижения?
- Какая потеря транзакций возможна при текущем режиме репликации?
- Как приложения переподключатся и как исключат повторное выполнение операции?
Последний пункт важен даже при нулевой потере данных на уровне базы. Клиент мог отправить транзакцию, сервер — зафиксировать её, а соединение оборвалось до ответа. Для клиента результат неоднозначен. Повтор запроса без защиты от дублей может создать повторный платёж, заказ или задачу. Для критичных операций продумывают идемпотентность и проверку результата, а не полагаются на то, что сетевой ответ всегда дойдёт.
Что измерять и где схема ломается
В PostgreSQL 17 состояние отправки WAL на основном сервере можно наблюдать через представление pg_stat_replication: в частности, смотреть позиции WAL и задержки записи, сброса и применения. Разница между текущей позицией WAL и позицией реплики помогает оценить отставание в объёме журнала. Но это не обещание, сколько именно секунд данных будет потеряно при аварии: скорость генерации WAL меняется, а задержка — показатель недавнего интервала, не гарантия будущего.
Практическая проверка — учения с реальным переключением на тестовой или выделенной среде. Запишите время последней подтверждённой транзакции, имитируйте отказ основного, продвиньте реплику по штатному сценарию и проверьте данные после переподключения приложения. Фиксируйте время обнаружения сбоя, продвижения, восстановления соединений и расхождение данных. Без такого теста нельзя честно обещать ни RPO, ни время восстановления.
Подход ломается на граничных сценариях: реплика отстала или недоступна, мониторинг принял сетевой сбой за отказ сервера, приложение продолжило писать в старый узел, а после переключения клиенты повторили незавершённые запросы. Отдельно проверяйте, что автоматизация выбирает актуальную реплику, а старый основной не возвращается в работу с прежней ролью.
Что делать дальше
Начните не с выбора инструмента failover, а с двух требований: сколько подтверждённых изменений допустимо потерять и сколько времени приложение может быть недоступно. Затем выберите режим репликации, проверьте последствия потери синхронного узла и проведите учение с фиксацией времени и данных. После этого настройте оповещения по отставанию WAL и проверку повторных запросов в приложении. Инвалидация кешей и резервное копирование решают отдельные задачи — здесь речь только о переключении основного сервера и потере транзакций.
1 WAL — журнал, в который PostgreSQL записывает изменения до того, как они попадут в основные файлы данных. Реплика использует этот журнал, чтобы воспроизвести изменения на своей копии.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: PostgreSQL 17: Warm Standby, PostgreSQL 17: параметры репликации
Частые вопросы
Можно ли гарантировать, что failover не потеряет подтверждённые транзакции?
Что произойдёт, если синхронная реплика станет недоступна?
Асинхронная реплика отстаёт на несколько секунд — столько данных и потеряется?
Почему после успешного переключения операция может выполниться дважды?
Нужно ли отдельно настраивать автоматическое переключение?
Эти рекомендации подходят для другой версии PostgreSQL?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.