33.2. Как это работает
Работая в обычном режиме, Postgres Pro запускает отдельный обслуживающий процесс для каждого входящего подключения. При включении пула соединений число обслуживающих процессов, которые могут использоваться для отдельно взятой базы данных, ограничивается значением session_pool_size. При достижении этого ограничения главный процесс postmaster перестаёт запускать новые обслуживающие процессы для соответствующих сеансов и передаёт последующие подключения одному из уже запущенных процессов. Так как один обслуживающий процесс Postgres Pro может работать только с одной базой данных, во встроенном пуле приходится поддерживать отдельные пулы соединений для каждой отдельной базы данных. Число таких пулов неограниченно: при появлении подключения к новой базе добавляется новый пул.
Для назначения сеанса соответствующему пулу postmaster должен узнать целевую базу данных, запрошенную клиентом, а для этого требуется получить и разобрать поступающий от клиента стартовый пакет. Чтобы эта процедура не стала узким местом, postmaster делегирует её одному из процессов-приёмников. Приёмник обрабатывает стартовый пакет и возвращает результат главному процессу. В зависимости от полученной информации, postmaster выбирает подходящий для этого клиента пул и передаёт в него соединение, используя механизм передачи дескрипторов файлов.
Примечание
Пул соединений можно отключить для некоторых пользователей или баз данных, перечислив их имена в параметрах dedicated_users и dedicated_databases, соответственно. Для таких пользователей и баз данных будут использоваться выделенные обслуживающие процессы в неограниченном количестве, то есть у этих соединений будет приоритет с точки зрения доступа к системным ресурсам.
Так как реализация пула на более низком уровне потребовала бы кардинально изменить механизм блокировок Postgres Pro, пул функционирует только на уровне транзакций. Это означает, что обслуживающий процесс может переключиться на выполнение другого сеанса только после завершения текущей транзакции. Однако встроенный пул сохраняет окружения сеансов для соединений, так что все изменения в контексте сеанса, производимые клиентским приложением, например, модифицированные параметры конфигурации сеанса, подготовленные операторы или временные таблицы, сохраняются/восстанавливаются при переключении обслуживающего процесса с одного сеанса на другой. Пул pgbouncer, напротив, поддерживает семантику сеансов только в сеансовом режиме, в котором число запускаемых обслуживающих процессов не ограничивается.
Сеансы, обслуживаемые пулом, привязываются к своим процессам и не могут перемещаться от одного к другому, так как для переноса потребовалось бы сериализовать и передать весь контекст сеанса, что является весьма нетривиальной задачей. По умолчанию обслуживающие процессы продолжают работать, даже когда все назначенные им сеансы завершаются. Для изменения этого поведения вы можете воспользоваться параметрами конфигурации restart_pooler_on_reload и idle_pool_worker_timeout.
33.2. How It Works
When running in the regular mode, Postgres Pro spawns a separate backend for each connection request. With connection pooling enabled, the number of backends that can be used for each database is limited by the session_pool_size value. Once this limit is reached, postmaster stops spawning new backend processes for the corresponding sessions and redirects further connection requests to one of the backends that has already been started. Since each Postgres Pro backend can work with a single database only, built-in connection pooler has to maintain separate connection pools for each database. The number of pools is unlimited: each time a new database needs to be served, a new pool is added.
To assign sessions to an appropriate pool, postmaster needs to know the target database for the client connection, which requires receiving and parsing a startup packet from the client. To avoid a bottleneck at this stage, postmaster delegates the task of reading the startup packet to one of the listener processes. The listener fetches the startup packet and returns the result back to postmaster. Based on the received information, postmaster chooses the pool for this client and redirects the connection to this pool using the file descriptor transfer mechanism.
Note
You can disable connection pooling for some databases and users by specifying them in the dedicated_databases and dedicated_users parameters, respectively. Such databases and users can use an unlimited number of dedicated backends, thus getting priority access to available system resources.
To avoid substantial changes in Postgres Pro locking mechanism, only transaction-level pooling policy is supported. In this mode, the backend can be rescheduled to another session only after it has completed the current transaction. However, the built-in pooler provides session semantics for pooled connections, so that all changes in the session context made by a client application, such as session configuration parameters, preparing statements, or creating temporary tables, are saved/restored by Postgres Pro when the backend is rescheduled to another session. By contrast, pgbouncer can provide session semantics only in the session pooling mode, which does not limit the number of launched backends.
Pooled sessions are bound to backends and cannot be migrated between them. Migrating a session would also require serialization and transfer of the complete session context, which is a non-trivial task. By default, pooled backends continue running even if all sessions assigned to them have been already terminated. To change this behavior, you can set restart_pooler_on_reload or idle_pool_worker_timeout configuration parameters.