SystemdDoctor
служба не работает базы данных пул соединений

Приложение ломается при работе через пул соединений

Пул соединений переиспользует соединения между клиентами, и в агрессивных режимах клиент не получает то же соединение дважды. Всё, что живёт в соединении — подготовленные запросы, временные таблицы, настройки сеанса, — перестаёт работать.

Вероятные причины

По порядку: сверху то, что встречается чаще.

  1. Режим пула не сохраняет состояние соединения

    В режиме на транзакцию соединение возвращается в пул после каждой транзакции. Состояние сеанса теряется.

  2. Пул исчерпан и клиенты ждут

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

  3. Приложение обращается напрямую к базе, минуя пул

    Часть соединений идёт мимо пула, и число соединений к базе оказывается больше расчётного.

Диагностика

Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.

Состояние пулов: клиенты, серверы, ожидающие.

psql -h 127.0.0.1 -p 6432 -U pgbouncer -c 'SHOW POOLS' 2>/dev/null

Сообщения пула о соединениях и отказах.

journalctl -u pgbouncer -n 30 --no-pager

Кто подключается к базе напрямую, а кто через пул.

sudo ss -tnp | grep -E ":5432|:6432" | head

Решение

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

1. Режим пула не сохраняет состояние соединения
Почему происходит
В режиме на транзакцию соединение возвращается в пул после каждой транзакции. Состояние сеанса теряется.
Как проверить
Посмотрите режим пула и ошибки приложения.
sudo grep -iE "^pool_mode" /etc/pgbouncer/pgbouncer.ini 2>/dev/null
journalctl -u myapp.service -n 20 --no-pager | grep -iE "prepared|temp table"
Как исправить
Либо перейдите на режим на сеанс, либо отключите подготовленные запросы в приложении. Оба решения рабочие, выбор зависит от нагрузки.
2. Пул исчерпан и клиенты ждут
Почему происходит
Число соединений к базе ограничено. При исчерпании клиенты ждут, и приложение видит таймауты.
Как проверить
Посмотрите состояние пула.
psql -h 127.0.0.1 -p 6432 -U pgbouncer -c 'SHOW POOLS' 2>/dev/null | head
sudo grep -iE '^(max_client_conn|default_pool_size)' /etc/pgbouncer/pgbouncer.ini 2>/dev/null
Как исправить
Согласуйте размер пула с числом соединений базы и нагрузкой приложения. Пул меньше нужного превращается в узкое место.
3. Приложение обращается напрямую к базе, минуя пул
Почему происходит
Часть соединений идёт мимо пула, и число соединений к базе оказывается больше расчётного.
Как проверить
Посмотрите, куда подключается приложение.
sudo ss -tnp | grep -E ":5432|:6432" | head
systemctl show myapp.service -p Environment | tr " " "\n" | grep -i host
Как исправить
Направьте все соединения через пул. Смешение прямых соединений и пула сводит на нет смысл ограничения.

Пример вывода

Подготовленный запрос не найден после возврата соединения в пул. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.

myapp[11800]: ERROR: prepared statement "stmt_1" does not exist (SQLSTATE 26000)
pgbouncer[11810]: C-0x55: app/app@10.0.0.9:51422 closing because: client unexpected eof (age=0s)

$ grep ^pool_mode /etc/pgbouncer/pgbouncer.ini
pool_mode = transaction

Связанные ошибки

Где встречается чаще всего

Источники

  • Документация PgBouncer: режимы пула документация программы
    сверено 15 сентября 2026
  • Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
    Воспроизведено подготовленным запросом при режиме пула на транзакцию.
    собственная проверка, systemd 255
    сверено 15 сентября 2026