Режимы пула
pg_doorman поддерживает два режима пула: transaction и session. Режим задаётся для пула, при необходимости переопределяется для конкретного пользователя.
Режима statement нет. Покул на уровне отдельного оператора ломает больше драйверов, чем помогает, а pg_doorman агрессивно оптимизирован под транзакционный режим (кеш prepared statements, direct handoff, FIFO-планирование).
Транзакционный режим (рекомендуется)
pools:
mydb:
pool_mode: "transaction"
Backend-соединение удерживается в течение транзакции и возвращается в пул при COMMIT, ROLLBACK или неявном завершении.
Именно этот режим даёт ту самую эффективность соединений, ради которой существует pg_doorman: pool_size равный 40 обслуживает тысячи клиентов, пока транзакции остаются короткими.
Что работает в транзакционном режиме (там, где большинство пулеров проваливаются):
- Prepared statements. pg_doorman кеширует их в рамках пула, переименовывает имена statement между backend-соединениями и прозрачно повторно готовит запрос. Драйверы, привязанные к
unnamed-statement (Go pgx, .NET Npgsql, Python asyncpg), работают без настройки. - Pipelined-батчи и асинхронный поток
Flush. - Cancel-запросы поверх TLS.
LISTEN/NOTIFY— но только внутри транзакции; кросс-транзакционные уведомления теряются (так же, как в PgBouncer).
Что в транзакционном режиме не работает:
SETиRESETвне транзакции. Используйте сессионный режим для клиентов, опирающихся на изменение GUC уровня сессии (SET TIME ZONE,SET search_pathодин раз на соединение).- advisory-блокировки, удерживаемые между транзакциями. Используйте сессионный режим.
- курсоры, удерживаемые вне транзакций (
WITH HOLD). Используйте сессионный режим. SET LOCALработает как ожидается — он ограничен транзакцией.
Сессионный режим
pools:
legacy_app:
pool_mode: "session"
Backend-соединение удерживается в течение клиентской сессии. В пул возвращается только при отключении клиента.
Используйте, когда:
- Приложение использует состояние уровня сессии (
SET search_path,SET TIME ZONE). - Приложение использует курсоры WITH HOLD.
- Приложение использует advisory-блокировки между транзакциями.
- Вы переезжаете с немодифицированного PgBouncer-развёртывания, работавшего в сессионном режиме, и хотите подмену один-в-один.
В сессионном режиме pool_size фактически равен максимальному числу одновременных клиентов. Размер пула подбирается так, чтобы соответствовать max_connections PostgreSQL минус резервы.
Переопределение для конкретного пользователя
Режим пула можно переопределить для конкретного пользователя:
pools:
mydb:
pool_mode: "transaction"
users:
- username: "app"
password: "md5..."
pool_size: 40
- username: "admin_tools"
password: "md5..."
pool_size: 4
pool_mode: "session"
Полезно, когда одному пользователю (инструменты эксплуатации, миграции) нужна семантика сессии, а основное приложение остаётся в транзакционном режиме.
Очистка при возврате в пул
Транзакционный режим в подробностях: когда бэкенд уходит обратно в пул, pg_doorman выполняет RESET ALL и ROLLBACK (если cleanup_server_connections: true, как по умолчанию). Это сбрасывает:
- значения
SETуровня сессии; - курсоры;
- имена prepared statements, которые драйвер привязал к конкретным backend-именам (кеш prepared statements pg_doorman переживает — он индексируется текстом запроса, а не именем statement на бэкенде);
- advisory-блокировки (
pg_advisory_unlock_allнеявно входит вRESET ALL).
DEALLOCATE ALL и DISCARD ALL со стороны клиента также инициируют сброс всего, что закешировано pg_doorman для этого клиента в кеше prepared statements. Кеш уровня пула не затрагивается.
Чтобы отключить очистку (ради производительности в жёстко контролируемых развёртываниях):
pools:
mydb:
pool_mode: "transaction"
cleanup_server_connections: false
Делайте так только если вы уверены, что приложение никогда не оставляет состояние сессии.
Справочник
- Параметр
pool_mode: Настройки пула. cleanup_server_connections: Настройки пула.- Размер пула: Pool Coordinator, Пул под нагрузкой.