Найти в Дзене
Postgres DBA

Patroni:"ERROR: Exception when called state_handler.last_operation() " привёл к "statement_timeout"

От мониторинга к оптимизации: как предупреждение «Patroni unhealthy» указало на исчерпание ресурсов PostgreSQL
В ходе эксплуатации кластера PostgreSQL под управлением Patroni система мониторинга зафиксировала эпизодические переходы мастер-узла в состояние unhealthy — при том, что уже через минуту статус восстанавливался. Первичный анализ указывал на слишком низкий statement_timeout, но глобальная
Оглавление
Когда даже слона уносит подводное течение.
Когда даже слона уносит подводное течение.

От мониторинга к оптимизации: как предупреждение «Patroni unhealthy» указало на исчерпание ресурсов PostgreSQL

В ходе эксплуатации кластера PostgreSQL под управлением Patroni система мониторинга зафиксировала эпизодические переходы мастер-узла в состояние unhealthy — при том, что уже через минуту статус восстанавливался. Первичный анализ указывал на слишком низкий statement_timeout, но глобальная конфигурация PostgreSQL и файлы Patroni не содержали этого параметра. Детальное расследование, охватившее логи, нагрузку на сервер и даже исходный код Patroni, позволило не только найти скрытый жёстко заданный тайм-аут (2 секунды), но и установить истинную причину нестабильности — высокую нагрузку на СУБД, при которой даже системные запросы перестали укладываться в этот лимит. В этой статье мы разбираем ход диагностики, ключевые выводы и объясняем, почему «тонкая настройка» Patroni в данном случае была бессмысленна без оптимизации ресурсов базы данных.

Стартовое сообщение системы мониторинга

...
Problem name: Patroni [ Node ] Running (1) was in unhealthy state more than 1 time for last 30m
Host: pg01n1
Severity: Warning
Operational data: Running (1), pg01v1, Replica (0)
Groups: DB/PostgreSQL, Service/OPR.35, Service/OPR.36 Trigger description: Patroni Running (1) cluster node in Running (1) state on pg01n1.
...

Логи Patroni и PostgreSQL

Patroni

2026-03-16 09:44:32,751 ERROR: Exception when called state_handler.last_operation()
2026-03-16 11:05:22,522 ERROR: Exception when called state_handler.last_operation()
...
2026-03-17 14:04:23,216 ERROR: Exception when called state_handler.last_operation()
2026-03-17 15:47:42,668 ERROR: get_postgresql_status

PostgreSQL

2026-03-17 11:09:15.330 MSK| postgres| Patroni heartbeat| postgres| [local]| 12118| 57014| ОШИБКА:  выполнение оператора отменено из-за тайм-аута
2026-03-17 11:09:15.330 MSK| postgres| Patroni heartbeat| postgres| [local]| 12118| 57014| ОПЕРАТОР:  SELECT CASE WHEN pg_catalog.pg_is_in_recovery() ..
...
2026-03-17 14:04:23.206 MSK| postgres| Patroni heartbeat| postgres| [local]| 12118| 57014| ОШИБКА:  выполнение оператора отменено из-за тайм-аута
2026-03-17 14:04:23.206 MSK| postgres| Patroni heartbeat| postgres| [local]| 12118| 57014| ОПЕРАТОР:  SELECT CASE WHEN pg_catalog.pg_is_in_recovery() ...
2026-03-17 11:46:43.740 MSK| postgres| Patroni restapi| postgres| [local]| 12594| 57014| ОШИБКА:  выполнение оператора отменено из-за тайм-аута
2026-03-17 11:46:43.740 MSK| postgres| Patroni restapi| postgres| [local]| 12594| 57014| ОПЕРАТОР:  SELECT CASE WHEN pg_catalog.pg_is_in_recovery() ...
...
2026-03-17 15:47:42.655 MSK| postgres| Patroni restapi| postgres| [local]| 12594| 57014| ОШИБКА:  выполнение оператора отменено из-за тайм-аута
2026-03-17 15:47:42.655 MSK| postgres| Patroni restapi| postgres| [local]| 12594| 57014| ОПЕРАТОР:  SELECT CASE WHEN pg_catalog.pg_is_in_recovery() ...

Анализ сообщения об ошибке

Предупреждение от системы мониторинга о том, что узел Patroni pg01n1 (с ролью pg01v1) за последние 30 минут более одного раза переходил в нездоровое состояние (unhealthy). На момент срабатывания триггера узел снова стал здоровым (значение метрики Running (1)). Operational data содержит Running (1), pg01v1, Replica (0):

· Running (1) – узел сейчас в рабочем состоянии.

· pg01v1 – идентификатор узла или имя роли в кластере.

· Replica (0) – узел не является репликой, т.е. скорее всего, это мастер.

Таким образом, мастер-узел кластера PostgreSQL под управлением Patroni периодически становился недоступным или не отвечал на проверки здоровья, но восстанавливался самостоятельно.

Анализ на основе логов PostgreSQL

⚠️1. Обнаруженные в логах PostgreSQL ошибки "ОШИБКА: выполнение оператора отменено из-за тайм-аута" для подключений от Patroni restapi с локального сокета являются ключевым свидетельством. Они показывают, что Patroni периодически не может выполнить свои служебные запросы к PostgreSQL в пределах установленного времени ожидания. Это приводит к тому, что Patroni считает узел нездоровым (unhealthy), после чего при следующей успешной проверке статус восстанавливается. Временные метки ошибок (11:46, 11:50, 12:08) хорошо коррелируют с периодом, за который триггер мониторинга зафиксировал множественные переходы в нездоровое состояние (около 12:09).

⚠️2.Ошибки "выполнение оператора отменено из-за тайм-аута" возникают не только у процесса Patroni restapi, но и у Patroni heartbeat, причём часто синхронно (например, в 11:46:43 и 11:50:42 оба процесса фиксируют ошибку с интервалом в 1 мс).

Это указывает на общую проблему на стороне PostgreSQL или сервера, затрагивающую все подключения Patroni. PID процессов (12118 для heartbeat, 12594 для restapi) разные, но ошибка одна.

Ключевые наблюдения

  • Ошибка 57014 (statement timeout): в сессиях Patroni установлен statement_timeout (или lock_timeout), и запросы не успевают выполниться за отведённое время. Поскольку запросы Patroni (проверка recovery, статуса и т.п.) крайне простые, их длительность в норме составляет миллисекунды. Значит, либо statement_timeout установлен нереалистично низко (менее секунды), либо в моменты ошибок PostgreSQL испытывает такую высокую нагрузку или блокировки, что даже простые запросы задерживаются.
  • Синхронность ошибок: в 11:46:43 оба процесса (heartbeat и restapi) получают тайм-аут одновременно. Это практически исключает проблемы на стороне конкретного процесса Patroni и указывает на глобальное торможение PostgreSQL или всей системы.

Гипотезы

‼️1. ОСНОВНАЯ ГИПОТЕЗА: Установлен слишком низкий statement_timeout для пользователя/базы Patroni 

2. Периодические пики нагрузки на PostgreSQL, вызванные:

  • Автовакуум тяжёлых таблиц.
  • Внешними ETL-процессами или отчётами.
  • Накоплением блокировок из-за долгих транзакций.

‼️3. Проблемы с дисковым вводом-выводом – например, высокая утилизация диска (await > 100 мс) может замедлять выполнение любых запросов, включая системные.

‼️4. Нехватка процессорных ресурсов – периодические скачки нагрузки от других процессов на сервере.

5. Конфликты блокировок – если Patroni обращается к системным таблицам или представлениям, которые заблокированы другими транзакциями (например, pg_stat_replication, pg_stat_activity могут блокироваться при некоторых операциях).

ОСНОВНАЯ ГИПОТЕЗА: Установлен слишком низкий statement_timeout для пользователя/базы Patroni

1.Анализ конфигурации Patroni/PostgreSQL

  • statement_timeout в PostgreSQL установлен в 8 часов (28800000 мс) через конфигурационный файл – глобально для всех сессий это очень большое значение, практически отключающее тайм-аут на выполнение операторов.
  • lock_timeout равен 0 (отключён).
  • В Patroni в файле patroni.yml найдены только параметры retry_timeout: 110, master_start_timeout: 300, master_stop_timeout: 300. Это тайм-ауты для операций управления кластером, но не для выполнения запросов к PostgreSQL.

2.Ключевой вывод

Ошибка 57014 (выполнение оператора отменено из-за тайм-аута) возникает, несмотря на огромный глобальный statement_timeout в PostgreSQL. Это означает, что Patroni сам устанавливает тайм-аут для своих сессийскорее всего, через параметр statement_timeout в секции postgresql.parameters конфигурации Patroni. Это значение, вероятно, слишком мало (например, 5–10 секунд), и в моменты пиковой нагрузки PostgreSQL не успевает ответить на простые запросы (проверка recovery, статуса), что приводит к отмене оператора на стороне сервера и, как следствие, к переходу узла в unhealthy.

3. В файле patroni.yml параметр statement_timeout отсутствует.

Однако ошибки 57014 в логах PostgreSQL продолжают возникать, что говорит о принудительной отмене запросов по тайм-ауту на стороне сервера. Глобальный statement_timeout в PostgreSQL установлен в 8 часов (через конфигурационный файл), поэтому причина не в глобальной настройке.

Отсюда следует, что statement_timeout задаётся одним из следующих способов:

  • На уровне роли пользователя (ALTER ROLE ... SET statement_timeout = ...).
  • На уровне базы данных (ALTER DATABASE ... SET statement_timeout = ...).
  • Через параметры подключения, передаваемые Patroni (например, через DCS, переменные окружения или postgresql.parameters в конфигурации, хранящейся в DCS, а не в локальном файле).
  • Через явную команду SET statement_timeout, выполняемую Patroni после установки соединения (менее вероятно, но возможно).

Таким образом, Patroni не устанавливает тайм-аут через локальный конфигурационный файл, но либо наследует его от настроек PostgreSQL, либо получает через DCS/параметры подключения. Это значение, вероятно, слишком мало (например, 5–10 секунд), и в моменты пиковой нагрузки простые запросы Patroni не успевают завершиться, вызывая ошибку 57014 и, как следствие, переход узла в состояние unhealthy.

4. Несмотря на отсутствие statement_timeout в глобальной конфигурации PostgreSQL, в настройках роли postgres, в выведенной конфигурации DCS (patronictl show-config) и в локальном файле patroni.yml, ошибки 57014 продолжают возникать в сессиях Patroni.

Это означает, что statement_timeout передаётся через параметры соединения — скорее всего, через переменную окружения PGOPTIONS, которая подхватывается libpq при установке подключения.

Источником может быть:

  • Файл окружения /etc/patroni_env.conf, указанный в systemd unit.
  • Переменные окружения, заданные непосредственно в systemd unit-файле Patroni.
  • Другой механизм (например, параметры в DSN, формируемые Patroni, но в данном случае маловероятно).

5. Продолжение анализа statement_timeout - обновлённый ключевой вывод

Несмотря на тщательную проверку:

  • глобальных настроек PostgreSQL (statement_timeout = 8h),
  • настроек роли postgres (пусто),
  • локального файла patroni.yml (отсутствует statement_timeout),
  • конфигурации кластера через patronictl show-config (нет statement_timeout),
  • переменных окружения процесса Patroni (нет PGOPTIONS),
  • systemd unit и файла окружения (отсутствуют),

ошибки 57014 продолжают возникать.

⚠️Это означает, что источник малого значения statement_timeout всё ещё не обнаружен, но он существует и влияет на сессии Patroni.

Возможные оставшиеся места:

1. DCS (распределённое хранилище конфигурации) – несмотря на вывод patronictl show-config, полная конфигурация может содержать параметры, не отображаемые этой командой, или параметры могут быть заданы на более глубоком уровне (например, в DCS есть ключ, который Patroni читает, но не показывает через show-config). Требуется прямой запрос к DCS.

2. Файл postgresql.auto.conf в PGDATA – Patroni записывает туда параметры из секции postgresql.parameters (взятой из DCS или локального файла) при каждом изменении конфигурации. Если в DCS есть statement_timeout, он окажется в этом файле и будет применён к PostgreSQL (но это повлияет на все сессии, включая Patroni). Однако глобальный statement_timeout уже 8h, что видно в pg_settings, значит, в postgresql.auto.conf его нет или он переопределён? Надо проверить.

3. Непосредственное выполнение команды SET statement_timeout в сессиях Patroni после подключения. ❗Это может делать сам Patroni в своём коде❗ (маловероятно, но возможно в старых версиях) или через параметры соединения, переданные в DSN (например, ?options=-c%20statement_timeout=10s). Такие параметры не видны в окружении, но могут быть частью строки подключения, формируемой Patroni из шаблона.

4. Файлы .pg_service.conf или .pgpass в домашней директории пользователя postgres, которые могут задавать параметры подключения по умолчанию.

5. Скрытые настройки на уровне кластера PostgreSQL, не отображаемые в pg_settings, например, через ALTER SYSTEM (но это видно в pg_settings с источником configuration file).

Альтернативные гипотезы возникновения ошибки 57014

Несмотря на тщательную проверку, источник малого значения statement_timeout не обнаружен. Однако ошибка «выполнение оператора отменено из-за тайм-аута» продолжает возникать.

Альтернативные объяснения, не связанные с явной установкой statement_timeout в конфигурации PostgreSQL или окружении Patroni.

ℹ️1. Неявный statement_timeout через параметры подключения, не отображаемые в окружении процессаℹ️

ℹ️Механизм: Patroni может формировать строку подключения, содержащую ➡️options=-c%20statement_timeout=...,⬅️ которая передаётся libpq и применяется к сессии, но не видна в переменных окружения процесса (так как передаётся через аргументы вызова или DSN). Это наиболее вероятная альтернатива, но технически это всё равно переопределение statement_timeout.

2. Конфликты репликации (если узел на самом деле является репликой)

Условие: Несмотря на Replica (0) в operational data, возможно, узел временно становится репликой или выполняет проверки на реплике. При включённом max_standby_streaming_delay долгие запросы на реплике могут отменяться, если они мешают применению WAL. Однако ошибка 57014 при этом не возникает – отмена из-за конфликта репликации даёт сообщение canceling statement due to conflict with recovery (код 40001). Но локализация может быть неточной? Проверить логи на наличие других сообщений.

3. Внешнее вмешательство (скрипты мониторинга или административные команды)

Механизм: Внешний процесс (например, скрипт, убивающий долгие запросы) может выполнять pg_cancel_backend() для сессий Patroni, если они выполняются дольше заданного порога. Это породило бы ошибку canceling statement due to user request (тоже класс 57014). Сообщение на русском может быть переведено как «из-за тайм-аута», если переводчик неточен. Проверить логи PostgreSQL на наличие других сессий, выполняющих отмену.

4. Достижение лимита времени на выполнение, установленного на уровне ядра или через ulimit

Механизм: Если для процесса PostgreSQL установлен мягкий лимит CPU (например, ulimit -t), превышение этого лимита приводит к отправке сигнала SIGXCPU, который может быть преобразован в отмену запроса. Однако обычно это убивает процесс целиком, а не отменяет оператор. Маловероятно.

5. Некорректная работа расширений (например, pg_stat_statements) или триггеров

Механизм: Некоторые расширения могут искусственно ограничивать время выполнения запросов. Например, pg_qualstats или собственные разработки. Проверить список установленных расширений: SELECT * FROM pg_extension;

6. Ошибка в PostgreSQL (баг), приводящая к ложному срабатыванию statement timeout

Механизм: В некоторых версиях PostgreSQL (особенно старых) были проблемы с тайм-аутами при определённых условиях (например, при работе с подготовленными транзакциями). Уточнить версию: SELECT version();

7. Тайм-аут на стороне клиента (Patroni), который интерпретируется сервером как отмена

Механизм: Если Patroni закрывает соединение из-за своего внутреннего тайм-аута , сервер может залогировать это как отмену оператора? Нет, закрытие соединения даёт ошибку «connection closed», а не отмену оператора.

8. Достижение lock_timeout (но у нас lock_timeout = 0)

Если lock_timeout был бы установлен, то при ожидании блокировки более этого времени запрос отменяется с ошибкой 55P03, не 57014.

9. Достижение idle_in_transaction_session_timeout (но он 1 час)

Patroni не держит транзакции открытыми длительное время, поэтому маловероятно.

10. Проблемы с сетевыми тайм-аутами (TCP user timeout)

Не приводит к ошибке 57014.

❗Гипотеза о влиянии проблем сети на возникновение ошибок Patroni heartbeat и restapi НЕ ПОДТВЕРЖДАЕТСЯ.

1. Анализ симптомов: почему это не сеть

Сетевые проблемы в кластере Patroni проявляются совершенно иначе, чем те ошибки, которые зафиксированы в ваших логах.

Логи (опровержение сетевой гипотезы):

  • Ошибки PostgreSQL (57014): ОШИБКА: выполнение оператора отменено из-за тайм-аута (SQLSTATE 57014). Это не ошибка соединения, а принудительная отмена уже выполняющегося запроса со стороны самого PostgreSQL. Запросы от Patroni (heartbeat и restapi) успешно доходят до базы данных, начинают выполняться, но не укладываются в отведенный лимит времени. Соединение между Patroni и PostgreSQL установлено.
  • Ошибки Patroni (get_postgresql_status): Эти ошибки являются прямым следствием предыдущих. Patroni отправляет запрос, ждет ответ, но так как PostgreSQL отменяет запрос, Patroni не получает ожидаемых данных и логирует исключение. Это ошибка получения статуса, а не потери связи.

Типичные логи при реальных сетевых проблемах (чего НЕТ в логах):

В логах Patroni: сообщения о недоступности узла, тайм-аутах соединения или ошибках DNS, например: WARNING: Request failed ... Max retries exceeded или ERROR: Request to server http://etcd:2379 failed: ReadTimeoutError / Connection timed out.

В логах PostgreSQL: записи о проблемах с подключением, например: LOG: connection received ..., FATAL: could not start WAL streaming, либо вообще отсутствие записей от Patroni, так как соединение не устанавливается.

Суть проблемы: невозможность установить соединение, тайм-аут ожидания ответа от узла или DCS, сброс соединения.

2. Как Patroni использует сеть и почему в вашем случае она ни при чем

Patroni полагается на сеть для двух ключевых взаимодействий:

1. Коммуникация с DCS (etcd/Consul): Для хранения кластерного состояния, выбора лидера и обнаружения сбоев. Проблемы с сетью на этом уровне приводят к тому, что Patroni не может обновить свой статус в DCS. Если лидер теряет связь с DCS, он инициирует собственную демоцию (понижение в роли), чтобы предотвратить "split-brain". В ваших логах нет признаков такой демоции.

2. Коммуникация между узлами: Узлы обмениваются информацией через REST API (порт 8008). При потере связи с мастером, реплики начнут выборы нового лидера, что также сопровождается специфическими предупреждениями. В ваших логах этого нет.

В данном случае сетевое взаимодействие между Patroni и PostgreSQL на уровне установки соединения не нарушено. Проблема начинается после того, как соединение уже установлено и запрос передан на выполнение.

3. Окончательный вывод и подтвержденная причина

Первоначальный анализ был полностью верен. ‼️Причина ошибок — тайм-аут выполнения сложных системных запросов Patroni на стороне PostgreSQL.‼️

Непосредственная причина: Запросы, которые Patroni отправляет для мониторинга (к функциям вроде pg_stat_get_activity(), pg_get_replication_slots()), выполняются дольше, чем позволяет лимит statement_timeout, установленный для сессий Patroni.

Корневая причина: Высокая нагрузка на PostgreSQL, связанная с огромным числом допустимых соединений (max_connections: 5000). Системные функции сканируют все 5000 слотов процессов, что при высокой конкуренции или длительных транзакциях может занимать секунды, превышая жесткий тайм-аут Patroni.

-2

💥Установленная корневая причина ошибки

‼️В patroni присутствует внутренний, зашитый statement_timeout для heartbeat запросов ‼️https://github.com/patroni/patroni/blob/v4.0.6/patroni/postgresql/config.py

local_conn_kwargs = {
local_address,
self._superuser,
'dbname': self._postgresql.database,
'fallback_application_name': 'Patroni',
'connect_timeout': 3,
'options': '-c statement_timeout=2000'
}

ℹ️Данный фрагмент кода находится в файле patroni/postgresql/config.py (версия 4.0.6) в методе ConfigHandler.resolve_connection_addresses.

ℹ️Этот словарь определяет параметры подключения, которые Patroni использует для установления локальных соединений с управляемым экземпляром PostgreSQL. После формирования local_conn_kwargs присваивается атрибуту conn_kwargs пула соединений (self._postgresql.connection_pool.conn_kwargs), и все внутренние операции (проверка состояния, выполнение запросов, изменение параметров и т.д.) используют именно эти параметры.

Разбор каждого элемента:

local_address

  • Распаковывает словарь, который хранит либо параметры для подключения через Unix-сокет, либо TCP-адрес. Выбор зависит от конфигурационного флага use_unix_socket.
  • Если флаг установлен и в postgresql.parameters.unix_socket_directories указан корректный каталог, local_address содержит host (путь к каталогу) и port.
  • В противном случае используется TCP: host — localhost (если PostgreSQL слушает на *, 0.0.0.0 или localhost), либо первый адрес из listen_addresses, а port — значение параметра port.

self._superuser

  • Распаковывает словарь с учётными данными суперпользователя, взятыми из секции authentication конфигурации Patroni. Обычно это ключи username и password. Примечательно, что сразу после формирования local_conn_kwargs выполняется проверка: если присутствует username, оно заменяется на user (потому что libpq ожидает именно user).
  • Это позволяет Patroni аутентифицироваться при подключении к локальной базе данных.

dbname: self._postgresql.database

  • Имя базы данных для соединения. По умолчанию это значение берётся из конфигурации Patroni (обычно postgres). Используется для выполнения команд, не зависящих от конкретной БД (например, pg_is_in_recovery).

fallback_application_name: 'Patroni'

  • Устанавливает имя приложения, которое будет отображаться в логах PostgreSQL (например, в pg_stat_activity). Это упрощает отладку и мониторинг: все внутренние подключения Patroni будут маркированы как Patroni.

connect_timeout: 3

  • Таймаут установки соединения в секундах. Если за 3 секунды соединение не установлено, попытка прерывается. Защищает Patroni от зависания при проблемах с сетью или недоступности сокета.

💥➡️options: '-c statement_timeout=2000'⬅️💥

  • Передаёт дополнительные параметры командной строки при запуске сеанса PostgreSQL. Здесь устанавливается statement_timeout = 2000 мс (2 секунды). Это предохраняет Patroni от выполнения слишком долгих SQL-запросов (например, при сборе статистики или изменении параметров) — любой запрос, выполняющийся дольше 2 секунд, будет прерван, что предотвращает блокировку работы Patroni.

Контекст использования

Метод resolve_connection_addresses вызывается при каждой перезагрузке конфигурации (reload_config), а также в процессе инициализации. Он вычисляет не только локальные параметры, но и адреса для репликации (local_replication_address), а также формирует URL для внешнего доступа (conn_url).

После того как local_conn_kwargs сформирован, он назначается пулу соединений. Все дальнейшие подключения к локальному PostgreSQL (например, для выполнения CHECKPOINT, получения статуса репликации, изменения параметров через ALTER SYSTEM) используют эти параметры. Таким образом, фрагмент критически важен для надёжной и безопасной работы Patroni с управляемым экземпляром.

Примечания

  • В коде присутствует логика, заменяющая username на user, если такой ключ есть в self._superuser. В исходном фрагменте вопроса этого преобразования нет, но оно выполняется сразу после создания словаря.
  • local_address также может быть пустым (если Unix-сокет не используется и listen_addresses не содержит локальных адресов). В этом случае libpq попытается подключиться через сокет по умолчанию (например, /tmp).
  • ℹ️Использование statement_timeout в options позволяет избежать ситуации, когда Patroni “зависает” из-за неожиданно долгого запроса, что особенно важно для цикла проверки состояния.
-3

Подтверждение гипотез

1. ОСНОВНАЯ ГИПОТЕЗА: Установлен слишком низкий statement_timeout для пользователя/базы Patroni - ПОДТВЕРЖДЕНО.☑️

2. Периодические пики нагрузки на PostgreSQL - КОСВЕННО ПОДТВЕРЖДЕНО.☑️

3. Проблемы с дисковым вводом-выводом – например, высокая утилизация диска (await > 100 мс) может замедлять выполнение любых запросов, включая системные - ПОДТВЕРЖДЕНО.☑️

4. Нехватка процессорных ресурсов – периодические скачки нагрузки от других процессов на сервере.☑️

5. Конфликты блокировок – если Patroni обращается к системным таблицам или представлениям, которые заблокированы другими транзакциями (например, pg_stat_replication, pg_stat_activity могут блокироваться при некоторых операциях) - НЕПОДТВЕРЖДЕНО.❓

Гипотеза "3. Непосредственное выполнение команды SET statement_timeout в сессиях Patroni после подключения. Это может делать сам Patroni в своём коде" - ПОДТВЕРЖДЕНО.☑️

На тестовом стенде повторить ситуацию не удалось, по причине невозможности создания нагрузки на СУБД приводящую к столь значительной деградации системных вызовов Patroni.

Утилизация ресурсов

Активные сессии СУБД
Активные сессии СУБД
Утилизация CPU
Утилизация CPU

ℹ️В период возникновения ошибок "ERROR: get_postgresql_status" - СУБД работает в режиме HighLoad.

Итог:

В данном случае ошибка "ERROR: get_postgresql_status" - является дополнительным индикатором работы СУБД в нештатном режиме. Для исправления ситуации необходимо оптимизировать ресурсы и производительность СУБД. Тонкий тюнинг параметров Patroni - не имеет смысла.

Послесловие

Таким образом, проведённое расследование показало, что за внешними симптомами — периодическими переходами узла Patroni в состояние unhealthy — стояло сразу два фактора: жёстко заданный на уровне кода тайм-аут выполнения запросов (2 секунды) и объективная деградация производительности PostgreSQL в моменты пиковой нагрузки. Попытки найти «лишний» statement_timeout в конфигурационных файлах оказались ложным следом, а истинная причина требовала анализа кода Patroni и оценки состояния СУБД.

⚠️Ключевой вывод: прежде чем изменять параметры таймаутов в обвязке, необходимо убедиться, что сама база данных работает в штатном режиме, иначе любая система мониторинга и управления будет лишь транслировать симптомы, а не лечить болезнь.

Дальнейшие действия должны быть сосредоточены на оптимизации ресурсов PostgreSQL — настройке автовакуума, анализе блокировок и снижении конкуренции за системные представления при высоком количестве подключений.