awesome-everything EN
↑ Обратно к восхождению

Базы данных

Режимы PgBouncer: session, transaction и statement

Суть Transaction mode даёт мультиплексирование 10–100×, но ломает SET, LISTEN, SQL PREPARE и session-level advisory locks; у каждого есть безопасный эквивалент для transaction mode.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 12 min

Команда переключает PgBouncer с session на transaction mode. Задеплоенный SET search_path = 'app, public' перестаёт работать. Приложение в продакшне шесть месяцев. Ничего не менялось — кроме режима pooler.

Три режима PgBouncer

Session mode: backend арендуется клиенту на всё время его соединения. PgBouncer по сути брокер соединений — 1:1 между клиентскими и backend-соединениями. Всё работает: SET, LISTEN, temp tables, session-level advisory locks, классический SQL PREPARE. Мультиплексирование нулевое; выигрыш только в auth offload и очереди.

Transaction mode: backend арендуется только на время одной транзакции (BEGIN…COMMIT, или один autocommit-запрос). Между транзакциями backend возвращается в пул и может перейти к другому клиенту. Именно этот режим даёт реальное мультиплексирование — 10 000-клиентское приложение работает на 20–50 backend. Цена: session state не сохраняется между транзакциями.

Statement mode: backend возвращается после каждого отдельного оператора. Транзакции из нескольких операторов запрещены. Применяется почти исключительно для PL/Proxy-style шардинга; не режим общего назначения.

Продакшн-дефолт — transaction mode: session mode отдаёт весь выигрыш от мультиплексирования; statement mode слишком ограничен для OLTP.

ФункциональностьSession modeTransaction modeФикс в transaction mode
Коэффициент мультиплексированияНет (1:1)10–100×
SET search_path при connectРаботаетТеряется после первой транзакцииALTER ROLE app SET search_path = …
SET LOCAL внутри транзакцииРаботаетРаботает (в рамках той транзакции)
LISTEN / NOTIFYРаботаетСломано — NOTIFY попадает на другой backendОтдельное session-mode соединение для LISTEN
SQL-уровень PREPARE name AS …РаботаетEXECUTE попадает на другой backendProtocol-level prepared statements (драйвер); PgBouncer 1.21+ обрабатывает их
pg_advisory_lock() session-levelРаботаетLock принадлежит тому backend, который обработал вызовpg_advisory_xact_lock() (transaction-level)
Temp tablesРаботаетМогут не сохраниться до следующей транзакцииON COMMIT DROP или перевести в обычную таблицу

Почему SET ломается в transaction mode

В session mode соединение клиента всегда привязано к одному backend. SET search_path = 'app, public' при старте выполняется на backend B1 и остаётся там навсегда.

В transaction mode PgBouncer возвращает B1 в пул после первого COMMIT. Следующий запрос от того же клиента может попасть на B2, который никогда не видел этот SET. Настройка невидима — молча исчезла.

Фикс: ALTER ROLE app SET search_path = 'app, public' — Postgres применяет это к каждому новому соединению для этой роли, поэтому каждый backend стартует с правильной настройкой независимо от того, какой именно был назначен.

Почему LISTEN ломается, и фикс через отдельное соединение

LISTEN channel регистрирует текущий backend для получения NOTIFY channel сообщений. В session mode backend постоянный — события поступают надёжно. В transaction mode backend возвращается в пул между транзакциями. NOTIFY попадает на тот backend, который выбирает Postgres, — он может обслуживать другого клиента; исходный listener никогда не получит событие.

Фикс: открываем одно выделенное соединение, которое обходит PgBouncer или использует session mode исключительно для LISTEN. Весь OLTP остаётся на transaction-mode пуле. Две connection string сосуществуют.

Почему это работает

Зачем в PgBouncer вообще есть session mode? Для команд, мигрирующих постепенно, и для приложений, которым genuinely нужна session-семантика (legacy PREPARE, session advisory locks, долгоживущие temp tables). Session mode — безопасный дефолт; transaction mode — апгрейд производительности, требующий предварительного аудита приложения.

Сравнение режимов PgBouncer
Session mode: мультиплексирование
Нет (1:1)
Transaction mode: мультиплексирование
10–100×
Statement mode: применение
Только PL/Proxy шардинг
Default pool_size
20
Default max_client_conn
100
Память PgBouncer на pooled conn
~2 КБ
Память backend Postgres
~5–10 МБ
Prepared statements в tx mode
PgBouncer 1.21+
Викторина

Команда переключает PgBouncer с session на transaction mode, и `SET search_path = 'app, public'` при connect перестаёт работать. Почему?

Викторина

Лучший вариант, если приложению на PgBouncer transaction mode нужен LISTEN/NOTIFY для инвалидации кеша?

Расставь шаги по порядку

Упорядочи задачи при переходе на transaction mode PgBouncer — от наибольшего к наименьшему приоритету:

  1. 1 Аудит SET (не SET LOCAL) — мигрировать на ALTER ROLE или SET LOCAL
  2. 2 Аудит классических SQL PREPARE — перейти на protocol-level (через драйвер)
  3. 3 Аудит LISTEN — изолировать на выделенном session-mode соединении
  4. 4 Аудит pg_advisory_lock (session-level) — переключить на pg_advisory_xact_lock
  5. 5 Включить max_prepared_statements 1000 (PgBouncer 1.21+) для protocol prepares
  6. 6 Установить server_reset_query = DISCARD ALL при риске утечки состояния
  7. 7 Установить idle_in_transaction_session_timeout в Postgres GUC как safety net
Вспомните перед уходом
  1. 01
    Объясни, что меняется при переходе с session mode на transaction mode в PgBouncer — что работает, что ломается, что становится возможным.
  2. 02
    Почему LISTEN ломается в transaction mode PgBouncer и каков правильный архитектурный фикс?
  3. 03
    Что делает server_reset_query = DISCARD ALL в PgBouncer и когда это необходимо?
Итог

PgBouncer предлагает три режима: session (1:1, нулевое мультиплексирование, всё работает), transaction (мультиплексирование 10–100×, требует аудита приложения) и statement (только для шардинг-прокси). Transaction mode — продакшн-стандарт. Он ломает четыре паттерна — SET вне транзакции (фикс: ALTER ROLE), LISTEN (фикс: выделенное session-mode соединение), SQL-уровень PREPARE (фикс: protocol-level через драйвер, PgBouncer 1.21+) и session-level advisory locks (фикс: pg_advisory_xact_lock). У каждой поломки есть точный эквивалент, безопасный в transaction mode; ни одна функциональность не теряется — только переносится.

Связанные уроки
встречается в258
Продолжить восхождение ↑Размер пула: формула (ядра × 2) + шпинделей и двухуровневый стек
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources4
expand
  1. 01
  2. 02
  3. 03
  4. 04

Trademarks belong to their respective owners. Editorial reference only.