PostgreSQL под нагрузкой: что первым ломается при failover
При аварийном переключении PostgreSQL риск зависит не только от настроек репликации: под нагрузкой растут задержка и отставание standby, а слот репликации может удерживать WAL до заполнения диска. Разбираем, что проверять и чем приходится платить за защиту данных.

В PostgreSQL 16 асинхронная реплика может отставать от primary именно тогда, когда запись идёт плотным потоком: если primary пропадёт, последние подтверждённые клиентам транзакции могут не попасть на standby. Синхронная реплика уменьшает этот риск, но добавляет ожидание к записи и сама становится частью пути каждого commit. Под нагрузкой отказоустойчивость ломается не в одной точке: сначала растёт задержка или очередь WAL, затем система выбирает между доступностью и потерей данных.
Сначала определите, что значит «не потерять данные»
Failover — переключение на реплику после отказа основного сервера. У него две разные цели: как быстро приложение снова обслуживает запросы и сколько подтверждённых записей допустимо потерять. Первая задаёт RTO — приемлемое время восстановления. Вторая — RPO, допустимую потерю данных. Ни репликация, ни автоматическое переключение сами по себе не гарантируют нулевой простой и нулевую потерю.
При асинхронной репликации primary не ждёт, пока standby получит WAL перед подтверждением транзакции. Если primary внезапно погибнет, реплика может не успеть получить или воспроизвести часть журнала. «Запрос завершился успешно» в приложении здесь не означает «эта транзакция уже есть на любой реплике».
Термин. WAL (Write-Ahead Log) — журнал, в который PostgreSQL записывает изменения до их применения к файлам данных. Реплика получает WAL и воспроизводит его; задержка передачи и задержка воспроизведения — разные вещи.
Что ломается первым под нагрузкой
1. Растёт цена синхронной записи
В синхронном режиме commit может ждать подтверждения от синхронной standby. Значение synchronous_commit = on при настроенной синхронной репликации ждёт, пока удалённая сторона сбросит WAL на устойчивое хранилище. Поэтому задержка записи зависит уже не только от primary: на неё влияют сеть и дисковая подсистема реплики. Если standby перегружена, медленно сбрасывает WAL или сеть теряет скорость, ожидание появляется у транзакций приложения.
Это не означает, что любая репликация автоматически защищает commit. Если синхронная standby не настроена или недоступна, поведение зависит от конфигурации; само значение параметра не превращает асинхронную репликацию в синхронную. А режим remote_apply ждёт не только сброса WAL на standby, но и применения изменений: чтения с реплики становятся актуальнее, но commit ждёт дольше.
2. Асинхронная реплика отстаёт и может потерять хвост
При высокой скорости генерации WAL standby может не успевать его принимать или применять. Если primary потерян до доставки последних записей, продвижение отстающей реплики к роли primary способно отбросить транзакции, которые приложение уже считало успешными. Чем дольше реплика отстаёт, тем больше потенциальное окно потери. Одной цифры «задержка репликации» недостаточно: важно понять, измеряет ли она передачу, запись на диск или воспроизведение журнала.
3. Репликационный слот удерживает WAL на основном сервере
Слот помогает не удалить журнал, который ещё нужен отстающей реплике. Но если потребитель надолго остановился, WAL продолжает занимать место на primary. При неограниченном удержании журналов последствия могут дойти до заполнения диска — и тогда проблема репликации становится проблемой доступности самой базы. Если задан предел хранения WAL слотом, после его превышения реплика может потерять возможность продолжить с сохранённого места и потребовать пересоздания или другого восстановления.
4. Переключение поднимает не тот сервер или поднимает его дважды
Promotion — перевод standby в primary — не должен запускаться, пока старый primary может продолжать принимать записи. Иначе возникает split brain: два узла считают себя основными, а приложение может записывать данные в оба. После этого недостаточно просто «вернуть старый сервер»: нужно определить, какой узел источник истины, и согласовать восстановление отставшего узла. Автоматизация failover должна включать не только обнаружение сбоя, но и fencing — надёжное предотвращение записи на прежний primary.
Реплика защищает данные только в пределах того, что она успела получить и сохранить. Автоматическое переключение отвечает за скорость реакции, но не отменяет вопроса, какой объём подтверждённых транзакций выдержит ваша схема.
Цена трёх режимов ожидания
В PostgreSQL 16 значение synchronous_commit задаёт, какого подтверждения ждать при commit. Варианты ниже не взаимозаменяемы, а фактическая гарантия зависит и от настройки синхронных standby.
| Режим | Что ждёт primary | Цена и ограничение |
|---|---|---|
on | При настроенной синхронной репликации — подтверждения сброса WAL на standby | Защищает подтверждённые записи от потери при отказе primary в пределах этой схемы; запись зависит от сети и диска standby |
remote_write | Standby записала WAL в операционную систему | Не равнозначен сбросу на устойчивое хранилище: сбой ОС или питания standby может привести к потере ещё не сброшенных данных |
remote_apply | Standby применила WAL | Подтверждённые изменения доступны на реплике, но добавляется ожидание воспроизведения |
off | Не ждёт подтверждения реплики перед commit | Меньше ожидание репликации, но шире окно возможной потери при аварии |
Для выбора синхронных реплик PostgreSQL 16 поддерживает режимы с приоритетом и кворумом через synchronous_standby_names. Кворум может позволить commit после ответа нужного числа реплик, но не отменяет требований к их независимости и доступности. Несколько standby за одним источником питания, одной стойкой или одним сетевым маршрутом не дают независимой защиты от общего отказа.
Что измерять до аварии
Не ориентируйтесь только на состояние «реплика подключена». Смотрите на скорость генерации WAL, доступное место на диске, очередь и задержки репликации, а также время, необходимое standby, чтобы применить накопившийся журнал. На primary представление pg_stat_replication показывает состояние подключённых отправителей WAL и доступные задержки записи, сброса и воспроизведения. Эти значения нужно читать вместе с нагрузкой и временными графиками: короткий снимок не показывает, как быстро растёт отставание.
pg_last_xact_replay_timestamp() тоже не универсальный счётчик лага: при отсутствии новых транзакций на primary время последнего воспроизведения может выглядеть старым, хотя реплика догнала базу. Для оценки отставания используйте несколько сигналов, включая позиции WAL и задержки на передаче, сбросе и воспроизведении.
Проверяйте сценарий отказа на тестовом окружении или в согласованном учении, а не впервые во время аварии. Важен весь путь: обнаружение отказа, изоляция старого primary, promotion standby, переключение соединений приложения и проверка целостности данных. Пул соединений может продолжать обращаться к старому адресу, а очередь повторных запросов после переключения — создать новый пик нагрузки.
Где гарантия ломается
- Синхронная реплика недоступна. В зависимости от конфигурации записи могут ждать её возвращения. Нужно заранее определить, что важнее при таком отказе: продолжать запись с ослабленной гарантией или остановить подтверждение транзакций.
- Успешный failover скрывает потерянные записи. Если приложение получило подтверждение от старого primary, а standby не успела получить соответствующий WAL, после переключения данные придётся сверять с внешними источниками или журналом операций.
- Заканчивается место под WAL. Контролируйте рост журналов и состояние слотов; не считайте слот заменой мониторингу диска.
- Старая primary возвращается в сеть. До повторного включения записи узел должен быть безопасно согласован с новым primary. Не запускайте оба как независимые источники изменений.
Ни один режим не защищает от ошибочного удаления, повреждения данных, которое реплика тут же повторит, или потери всей площадки, если копии находятся рядом. Репликация — часть плана восстановления, а не замена резервным копиям.
Что делать дальше
Начните не с переключения параметра, а с измеримых требований: сколько подтверждённых транзакций допустимо потерять и сколько времени можно не принимать запись. Затем выберите синхронную или асинхронную схему, проверьте поведение при недоступности standby и настройте оповещения на рост задержки, удержание WAL и свободное место. Следующий практический шаг — регулярно репетировать failover с проверкой fencing, подключения приложения и восстановления прежнего primary. Инвалидация бизнес-операций после потери подтверждённых записей — отдельная задача приложения.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: PostgreSQL 16: Warm Standby, PostgreSQL 16: Replication Configuration
Частые вопросы
Можно ли гарантировать, что при failover не потеряется ни одна подтверждённая транзакция?
Если синхронная реплика упала, PostgreSQL продолжит принимать записи?
Можно ли понять размер потери данных по одной метрике лага?
Что делать, если диск primary быстро заполняется WAL?
Что будет, если failover запустит два primary?
Если у меня другая версия PostgreSQL, настройки будут такими же?
Чем опасен failover в production, кроме потери транзакций?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.