PgBouncer — connection pooler для PostgreSQL: промежуточный слой между приложением и СУБД, управляющий пулом постоянных соединений. PostgreSQL создаёт отдельный OS-процесс на каждое подключение (~5–10 МБ RAM каждый), что делает 500 одновременных соединений проблематичными. PgBouncer поддерживает небольшой пул реальных соединений к PostgreSQL и мультиплексирует запросы от многих клиентов через них.
Режимы работы PgBouncer
- Session pooling — клиент получает соединение на всё время своей сессии; освобождает при отключении. Наиболее совместимый режим: работают prepared statements, LISTEN/NOTIFY, temporary tables. Экономия минимальная — помогает только при большом числе коротких сессий.
- Transaction pooling — соединение выдаётся только на время транзакции; между транзакциями используется другим клиентом. Максимальная эффективность: 1000 клиентских соединений к PgBouncer → 20–50 реальных соединений к PostgreSQL. Несовместим с prepared statements (в серверном режиме), LISTEN/NOTIFY, SET LOCAL.
- Statement pooling — соединение выдаётся только на время одного запроса. Только для простых SELECT без транзакций. Редко используется.
Когда нужен PgBouncer
Признаки, что connection pooler необходим:
- Число одновременных соединений к PostgreSQL регулярно превышает 100–200.
- Приложения используют short-lived connections — PHP-FPM создаёт новое соединение на каждый запрос.
- Ошибки «sorry, too many clients already» в логах PostgreSQL.
- Высокое потребление RAM на сервере PostgreSQL при умеренной нагрузке.
- Большой
pg_stat_activity: много соединений в состоянии «idle» без активных запросов.
Настройка PgBouncer
Минимальная конфигурация /etc/pgbouncer/pgbouncer.ini:
[databases]
mydb = host=127.0.0.1 port=5432 dbname=mydb
[pgbouncer]
listen_port = 6432
listen_addr = 127.0.0.1
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 25
reserve_pool_size = 5
reserve_pool_timeout = 3
Приложение подключается к PgBouncer на порт 6432 вместо PostgreSQL 5432. PgBouncer поддерживает 25 реальных соединений к PostgreSQL, обслуживая до 1000 клиентов. reserve_pool_size — дополнительные соединения при пиковой нагрузке.
История
PgBouncer создан Марко Тинтусом (Marko Kreen) из команды Skype в 2007 году. Skype обрабатывал сотни миллионов запросов к PostgreSQL, и масштабирование соединений стало критической задачей. PgBouncer стал ответом на фундаментальное ограничение PostgreSQL: один процесс на соединение. С 2020 года проект передан под управление сообщества PostgreSQL Global Development Group. PgBouncer 1.22 (2024) поддерживает PostgreSQL 16, TLS и Prometheus-метрики через встроенный endpoint.
PgBouncer vs ProxySQL (для MySQL)
| Параметр | PgBouncer | ProxySQL |
|---|---|---|
| СУБД | PostgreSQL | MySQL, MariaDB, Percona |
| Connection pooling | Да | Да |
| Read/Write split | Нет | Да |
| Query routing | Нет | Да (по regex) |
| Веб-интерфейс | Нет | Нет (SQL-based admin) |
Применение в хостинге
PgBouncer — обязательный компонент для VPS с PostgreSQL при использовании PHP-FPM (Laravel, Symfony, WordPress + PostgreSQL addon). Без пулера при 200 одновременных PHP-воркерах PostgreSQL создаёт 200 процессов, потребляя ~1–2 ГБ RAM только на соединения. С PgBouncer в transaction mode — 10–25 реальных соединений к БД, остальные ожидают в очереди у PgBouncer.
Для Django (Python) рекомендуется использовать Django + PgBouncer в session mode, так как Django ORM использует prepared statements, несовместимые с transaction mode. Для Rails + ActiveRecord — transaction mode работает нормально, если не использовать Advisory Locks.