# Часто задаваемые вопросы

> Часто задаваемые вопросы о PgBouncer

---

Индекс LLMS: [llms.txt](/ru/llms.txt)

---

--------

## Как подключиться к PgBouncer? {#how-to-connect-to-pgbouncer}

PgBouncer работает как сервер Postgres, поэтому достаточно направить клиент
на порт PgBouncer.

--------

## Как распределять запросы между несколькими серверами? {#how-to-load-balance-queries-between-several-servers}

PgBouncer не имеет встроенной конфигурации для нескольких узлов.
Распределение можно реализовать внешними средствами:

1.  Циклический перебор DNS. Укажите несколько IP-адресов для одного имени DNS.
    PgBouncer не выполняет поиск DNS при каждом новом соединении: он кэширует
    все IP-адреса и перебирает их циклически. Обратите внимание: если с одним
    именем связано более 8 IP-адресов, бэкенд DNS должен поддерживать протокол
    EDNS0. Подробности приведены в README.

2.  Используйте балансировщик соединений TCP, например
    [LVS](http://www.linuxvirtualserver.org/) или
    [HAProxy](https://www.haproxy.org/). На стороне PgBouncer может быть полезно
    уменьшить `server_lifetime` и включить `server_round_robin`: по умолчанию
    неактивные соединения повторно используются по алгоритму LIFO, который
    может плохо подходить для балансировки нагрузки.

--------

## Как выполнить переключение при отказе {#how-to-failover}

PgBouncer не имеет встроенной конфигурации резервного узла и не обнаруживает
отказы. Переключение можно реализовать внешними средствами:

1. Перенастройка DNS: после изменения IP-адреса, связанного с именем DNS,
   PgBouncer подключится к новому серверу. Это поведение настраивается двумя
   параметрами: `dns_max_ttl` задаёт срок действия одного имени узла, а
   `dns_zone_check_period` — частоту проверки изменений SOA зоны. Если запись
   SOA зоны изменилась, PgBouncer повторно запросит все имена узлов в этой зоне.

2. Запишите новый узел в конфигурацию и перезагрузите её в PgBouncer: отправьте
   SIGHUP или выполните в консоли команду `RELOAD`. PgBouncer обнаружит изменение
   конфигурации узла и подключится к новому серверу.

3. Используйте команду `RECONNECT`. Она предназначена для ситуаций, когда два
   предыдущих способа неприменимы, например когда упомянутый HAProxy направляет
   исходящие из PgBouncer соединения. `RECONNECT` просто заново открывает все
   серверные соединения. Поэтому выполните эту команду после того, как другой
   компонент изменит сведения о маршрутизации соединений.

--------

## Как использовать подготовленные операторы в сеансовом режиме пула? {#how-to-use-prepared-statements-with-session-pooling}

В сеансовом режиме пула запрос сброса должен удалять старые подготовленные
операторы. Для этого можно задать `server_reset_query = DISCARD ALL;` или как
минимум `DEALLOCATE ALL;`.

--------

## Как использовать подготовленные операторы в транзакционном режиме пула? {#how-to-use-prepared-statements-with-transaction-pooling}

Начиная с версии 1.21.0, PgBouncer может отслеживать подготовленные операторы
в транзакционном режиме пула и подготавливать их на лету в связанном серверном
соединении. Чтобы включить эту возможность, параметру `max_prepared_statements`
необходимо присвоить ненулевое значение. Подробности приведены в [документации
`max_prepared_statements`](/ru/docs/pgbouncer/config/#max_prepared_statements).

В зависимости от версии PHP/PDO может быть несовместим с поддержкой
подготовленных операторов PgBouncer ([#991]). PHP/PDO совместим только при
одновременном использовании [PHP 8.4+ **и** libpq 17][php-fix]. Поэтому для
установок со старыми версиями рекомендуется обновление либо отключение
подготовленных операторов на стороне клиента.

[php-fix]: https://github.com/php/php-src/commit/f35ad560b468e3e0a6c289949ba9b19af4fa3e7b

[#991]: https://github.com/pgbouncer/pgbouncer/issues/991

### Отключение подготовленных операторов в JDBC {#disabling-prepared-statements-in-jdbc}

Для JDBC следует добавить параметр `prepareThreshold=0` в строку соединения.

### Отключение подготовленных операторов в PHP/PDO {#disabling-prepared-statements-in-phppdo}

Чтобы отключить подготовленные операторы на стороне сервера, атрибуту PDO
`PDO::ATTR_EMULATE_PREPARES` обязательно нужно присвоить `true` при подключении:

    $db = new PDO("dsn", "user", "pass", array(PDO::ATTR_EMULATE_PREPARES => true));

или позднее:

    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

--------

## Как обновить PgBouncer без разрыва соединений? {#how-to-upgrade-pgbouncer-without-dropping-connections}

Можно выполнить поэтапный перезапуск по процедуре из
[раздела документации `SHUTDOWN WAIT_FOR_CLIENTS`](/ru/docs/pgbouncer/usage/#shutdown-wait_for_clients).

--------

## Как определить соответствие клиентов серверным соединениям? {#how-to-know-which-client-is-on-which-server-connection}

Выполните в консоли команды `SHOW CLIENTS` и `SHOW SERVERS`.

1.  Используйте `ptr` и `link`, чтобы сопоставить локальное клиентское
    соединение с серверным.

2.  Используйте `addr` и `port` клиентского соединения, чтобы определить
    соединение TCP от клиента.

3.  Используйте `local_addr` и `local_port`, чтобы определить соединение TCP
    с сервером.

--------

## Где устанавливать PgBouncer: на веб-сервере или сервере базы данных? {#should-pgbouncer-be-installed-on-the-web-server-or-database-server}

Это зависит от условий.

PgBouncer удобно устанавливать на веб-сервере при использовании короткоживущих
соединений: так минимизируется задержка их установки. (Перед использованием
соединения TCP требуется несколько циклов обмена пакетами.) Установка PgBouncer
на сервере базы данных удобна, когда к нему подключается множество разных узлов,
например веб-серверов: тогда их соединения можно оптимизировать вместе.

PgBouncer можно установить и на веб-сервере, и на сервере базы данных. Недостаток
такой схемы в том, что каждый переход через PgBouncer добавляет небольшую
задержку к каждому запросу.

В конечном счёте необходимо проверить, какая модель лучше соответствует
требованиям к производительности. Следует также учесть, как установка PgBouncer
повлияет на переключение приложений при отказе веб-сервера или сервера базы данных.
