Получить доступ

Зачем нужен пул соединений к базе и как выбрать его размер?

MiddleСеть и ввод-вывод
Ещё спрашивают так:
  • Почему нельзя открывать соединение на каждый запрос?
  • Что такое PgBouncer?
  • Почему пул на 500 соединений работает хуже, чем на 50?
Коротко

Установка соединения — TCP, TLS, аутентификация, а в PostgreSQL ещё и новый процесс: миллисекунды и память. Пул держит готовые соединения и ограничивает их число.

  • Размер пула базы — небольшой: порядка ядер базы × 2, а не «по числу потоков приложения»
  • Больше соединений, чем база может обрабатывать параллельно, — только очереди внутри базы и конкуренция за блокировки
  • Сумма пулов всех экземпляров приложения не должна превышать лимит базы — отсюда PgBouncer

А ещё HTTP-клиенты тоже: keep-alive и пул соединений к каждому хосту

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Цена соединения. Новое соединение к PostgreSQL: TCP-рукопожатие, TLS, аутентификация, запуск отдельного серверного процесса (fork) с собственной памятью — единицы миллисекунд и мегабайты памяти на сервере. Делать это на каждый запрос — удвоить задержку и нагрузку. Пул (HikariCP, pgxpool, SQLAlchemy pool) открывает соединения заранее и раздаёт их запросам на время транзакции.

Почему пул должен быть маленьким. Интуиция «больше соединений — больше параллелизма» неверна. База выполняет параллельно столько, сколько у неё ядер и дисковой очереди. Лишние соединения:

  • конкурируют за CPU — переключения контекста;
  • конкурируют за блокировки и буферы — растёт время каждого запроса;
  • тратят память на сервере (work_mem на каждый сортирующий запрос!).

Пропускная способность при 50 соединениях часто выше, чем при 500, а задержка — ниже. Отправная формула (HikariCP): соединений ≈ ядра базы × 2 + число дисков. Дальше — по нагрузочным тестам. Ожидание свободного соединения в пуле лучше, чем очередь внутри базы: его видно метрикой и им можно управлять (таймаут на получение соединения).

Сумма пулов. 40 экземпляров приложения × пул 20 = 800 соединений, а PostgreSQL комфортно держит сотни. Решения:

  • уменьшить пулы экземпляров;
  • PgBouncer (Odyssey, pgcat) между приложением и базой: тысячи клиентских соединений мультиплексируются на десятки серверных. Режим transaction pooling — серверное соединение выдаётся на время транзакции; ограничения — сессионное состояние (prepared statements исторически, SET, advisory locks, временные таблицы);
  • закон Литтла для проверки: RPS к базе × время транзакции = нужное число одновременно занятых соединений.

Практика:

  • держать соединение только на время транзакции; не делать внешние HTTP-вызовы, пока соединение взято, — пул кончится;
  • таймауты: получение соединения из пула, запрос (statement_timeout), простаивающая транзакция (idle_in_transaction_session_timeout);
  • метрики пула: занято, ожидающих, время ожидания;
  • проверка живости соединений и пересоздание после переключения мастера.

HTTP-клиенты — та же история: keep-alive и пул соединений на хост экономят TCP- и TLS-рукопожатия; один клиент на приложение, а не новый на каждый запрос (иначе TIME_WAIT и исчерпание портов).

Пример

Приложение: 12 экземпляров × HikariCP maximumPoolSize=10 → 120 соединений.
База: 16 ядер, SSD → разумно ~32–40 активных.
Сделали: PgBouncer в transaction-режиме, default_pool_size=40;
приложение может держать хоть 1000 клиентских соединений, база видит 40.
Пропускная способность выросла, p99 упал: запросы ждут в пуле, а не дерутся в базе.

Что хотят услышать

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

Частые ошибки

  • Ставить пул по числу потоков приложения (200).
  • Брать соединение в начале обработки HTTP-запроса и держать до конца.

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем