← Назад к вопросам

Что такое PGBalancer в PostgreSQL?

3.0 Senior🔥 81 комментариев
#DevOps и инфраструктура#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

PgBouncer в PostgreSQL — управление пулом соединений

Вопрос, вероятно, имеет в виду PgBouncer (не PGBalancer), который является одним из самых популярных инструментов для управления пулом соединений в PostgreSQL. PgBouncer — это легковесный connection pooler, написанный на C, который действует как промежуточный слой между приложениями и базой данных.

Зачем нужен PgBouncer?

PostgreSQL имеет ограничение на количество одновременных соединений (по умолчанию около 100). Если каждое клиентское подключение создаёт прямое соединение с БД, база данных быстро исчерпает лимит соединений.

Проблема без PgBouncer:

  • Приложение с 1000 пользователей создаёт 1000 соединений с БД
  • Каждое соединение использует память на сервере БД
  • PostgreSQL исчерпывает лимит соединений → новые запросы отклоняются

Решение с PgBouncer:

  • 1000 пользователей подключаются к PgBouncer
  • PgBouncer переиспользует небольшой пул соединений (например, 20-50) к БД
  • Пользователи конкурируют за места в пуле, но БД не перегружается

Принцип работы

Приложение 1 ──┐
Приложение 2 ──┤
Приложение 3 ──┼──> PgBouncer ──> PostgreSQL (5 соединений)
Приложение 4 ──┤
Приложение 5 ──┘

Установка и конфигурация

На Linux:

sudo apt-get install pgbouncer

Конфиг pgbouncer.ini:

[databases]
# Имя БД в приложении = реальное имя на сервере
myapp = host=localhost port=5432 dbname=mydb

[pgbouncer]
# Количество соединений в пуле
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 25
min_pool_size = 10
reserve_pool_size = 5
reserve_pool_timeout = 3

# Логирование
logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer.pid

listen_port = 6432
listen_addr = 127.0.0.1

Режимы работы PgBouncer

1. Session Mode (сессионный режим)

pool_mode = session
  • Одно клиентское соединение привязано к одному соединению в пуле на всю сессию
  • Клиент получает одно и то же серверное соединение до отключения
  • Если в пуле нет свободного соединения, клиент ждёт
  • Использование: Когда клиент использует особенности сессии (временные таблицы, SET переменные)

2. Transaction Mode (транзакционный режим)

pool_mode = transaction
  • Соединение переиспользуется после каждой завершённой транзакции
  • Клиент может получить разные серверные соединения для разных транзакций
  • Более эффективное использование пула
  • Ограничение: Не поддерживает курсоры через транзакции, временные таблицы

3. Statement Mode (режим оператора)

pool_mode = statement
  • Соединение освобождается после каждого SQL-оператора
  • Максимально эффективное переиспользование
  • Ограничение: Очень ограниченный; нельзя использовать многооператорные транзакции

Типичная конфигурация для Node.js приложения

[databases]
app_prod = host=db.prod.example.com port=5432 dbname=app_db
app_dev = host=localhost port=5432 dbname=app_dev

[pgbouncer]
# Режим: транзакционный идеален для REST API
pool_mode = transaction

# Максимум клиентских соединений
max_client_conn = 1000

# Размер пула: если приложение создаёт 500 соединений одновременно,
# нужно выделить достаточно соединений к БД
# Правило: min_pool_size * кол-во баз >= макс. параллельные транзакции
default_pool_size = 25
min_pool_size = 10
reserve_pool_size = 5
reserve_pool_timeout = 3

# Таймауты
server_lifetime = 3600
server_idle_timeout = 600
client_idle_timeout = 900

# Аутентификация
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt

listen_port = 6432
listen_addr = 0.0.0.0

Использование с Node.js / Express

import { Pool } from 'pg';

// Подключаемся к PgBouncer, а не напрямую к PostgreSQL
const pool = new Pool({
  host: 'localhost',      // Адрес PgBouncer
  port: 6432,             // Порт PgBouncer (не 5432!)
  database: 'myapp',
  user: 'app_user',
  password: 'secure_password',
  max: 5,                 // Соединений в пуле приложения
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});

export default pool;

Мониторинг PgBouncer

Подключение к админской консоли:

psql -h localhost -p 6432 -U pgbouncer pgbouncer

Полезные команды:

-- Показать статус пула
SHOW POOLS;

-- Показать статистику по клиентам
SHOW CLIENTS;

-- Показать статистику по серверам
SHOW SERVERS;

-- Показать состояние статистики
SHOW STATS;

-- Перезагрузить конфиг без перезагрузки
RELOAD;

-- Безопасно завершить все соединения
SHUTDOWN;

Пример мониторинга в приложении

import { Client } from 'pg';

async function checkPgBouncerHealth() {
  const client = new Client({
    host: 'localhost',
    port: 6432,
    database: 'pgbouncer',
    user: 'pgbouncer',
    password: 'pgbouncer_password',
  });

  try {
    await client.connect();
    
    // Показать статистику пула
    const result = await client.query('SHOW POOLS');
    console.log('PgBouncer pools:', result.rows);
    
    // Проверить состояние
    const stats = await client.query('SHOW STATS');
    const totalRequests = stats.rows.reduce((sum, row) => sum + row.xact_count, 0);
    
    return {
      healthy: true,
      totalRequests,
      pools: result.rows
    };
  } catch (error) {
    console.error('PgBouncer health check failed:', error);
    return { healthy: false };
  } finally {
    await client.end();
  }
}

Проблемы и решения

Проблема: "no more connections"

Решение: Увеличить default_pool_size или max_client_conn

default_pool_size = 40  # Вместо 25
max_client_conn = 2000  # Вместо 1000

Проблема: "server closed the connection unexpectedly"

Решение: Увеличить server_lifetime или уменьшить server_idle_timeout

server_lifetime = 7200  # Переподключение каждые 2 часа
server_idle_timeout = 900  # Закрывать неиспользуемые за 15 минут

Проблема: Временные таблицы не работают в транзакционном режиме

Решение: Либо переключиться на session mode, либо использовать постоянные таблицы

Альтернативы PgBouncer

  • Pgpool-II — более мощный, поддерживает балансирование нагрузки и репликацию
  • Pooled connections в облаках — AWS RDS Proxy, Google Cloud SQL Proxy, Heroku Postgres Stunnel

Best Practices

1. Рассчитай размер пула правильно

pool_size = (core_count * 2) + effective_spindle_count
// Для 4-ядерного сервера: (4 * 2) + 1 = 9 соединений в пуле

2. Мониторь метрики PgBouncer

// В Prometheus/Grafana
SELECT
  datname,
  COUNT(*) as connection_count,
  state
FROM pg_stat_activity
GROUP BY datname, state;

3. Используй statement mode осторожно

// Проблемный код со statement mode:
const result1 = await pool.query('BEGIN');
const result2 = await pool.query('SELECT 1');
// Если между BEGIN и SELECT переключится соединение в пуле → ошибка!

4. Установи правильные таймауты

# Слишком короткий таймаут = часые переподключения
client_idle_timeout = 900  # 15 минут — хороший баланс
server_idle_timeout = 600  # 10 минут

PgBouncer — это essential инструмент для production-приложений, работающих с PostgreSQL, позволяющий масштабировать количество клиентов без перегрузки базы данных.