Как мне настроить PGbouncer для работы с SET search_path по запросам? - PullRequest
0 голосов
/ 13 декабря 2018

У меня довольно большая база данных PostgreSQL с до 300 подключенными клиентами из веб-приложения и некоторой фоновой обработкой.

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

Справочная информация

Мое веб-приложение является многопользовательским приложением.Например, у меня есть немецкая версия моего сайта на www.my-app.de и американская версия на www.my-app.com.Данные по каждой стране разбиты на отдельные SCHEMAS в postgresql.Таким образом, для каждого HTTP-запроса веб-приложение переключается между наборами данных в PostgreSQL, запуская запрос, устанавливая search_path следующим образом: если www.my-app.com, то SET search_path = 'us'.Это действительно удобно с точки зрения приложения, однако я думаю, что это противоречит возможностям создания пула соединений?

Проблема

Таким образом, в каждом HTTP-запросе search_path устанавливается для всего запроса, и в запросе может быть много запросов к базе данных.Насколько я понимаю, если бы у меня PGbouncer выполнял пул соединений, я мог бы рискнуть первым запросом в запросе на соединение с параметром search_path, установленным на us, и следующим запросом на соединение с параметром search_path, установленным на de..

Вопрос

Есть ли способ избежать такого поведения с PGbouncer?Или, может быть, альтернативный шаблон, который я мог бы использовать для уменьшения накладных расходов на соединение?

1 Ответ

0 голосов
/ 21 декабря 2018

Существует хороший список ограничений PgBouncer для PostgreSQL Wiki .SET находится в этом списке.

Предполагая, что вы хотите pool_mode = transaction в PgBouncer - это наиболее разумный режим, и у вас есть некоторый код приложения, зависящий от настроек сеанса (например, search_path), единственный способ сохранить состояние сеанса - это использовать транзакции.

Если ваше приложение просто создает соединение с PgBouncer, запускает на нем SET search_path TO us, а затем запускает несколько SELECT - это не будет работать.

Все это легко доказать - просто подключитесь с помощью psql к PgBouncer и используйте команду SET:

(postgres.example.com:6432) prod=# SET client_min_messages TO debug;
SET
(postgres.example.com:6432) prod=# SHOW client_min_messages ;
 client_min_messages 
---------------------
 notice
(1 row)

Как мы видим, состояние сеанса не сохраняется.Вам нужна транзакция:

(postgres.example.com:6432) prod=# begin;
BEGIN
(postgres.example.com:6432) prod=# SET client_min_messages TO debug;
SET
(postgres.example.com:6432) prod=# SHOW client_min_messages ;
 client_min_messages 
---------------------
 debug
(1 row)

(postgres.example.com:6432) prod=# COMMIT;
COMMIT

Другими словами - чтобы включить пул транзакций, транзакции должны быть без состояний - точно так же, как HTTP-запросы, которые переносят всю информацию о состоянии внутри (вформа файлов cookie, идентификаторы сеанса и т. д.).

Очевидно, что в вашем случае это означает внесение изменений в код приложения.Добавление «обертки» вокруг каждого звонка.Это довольно уродливо, и если вам нужно пойти по этому пути, попробуйте переписать приложение, чтобы использовать явный код страны в качестве столбца параметра или базы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...