如何配置PGbouncer在查询之间使用SET search_path?

时间:2018-12-13 16:34:32

标签: postgresql pgbouncer

我有一个很大的PostgreSQL数据库,最多可以通过一个Web应用程序和一些后台处理来连接300个客户端。

我正在考虑添加PGbouncer,因为据我了解,由于连接开销大,postgresql在这么多的连接中将无法继续很好地扩展。

背景

我的Web应用程序是多租户应用程序。例如。我在www.my-app.de上有我的网站的德语版本,在www.my-app.com上有我的网站版本。每个国家/地区的数据在postgresql中分为单独的var array: [Int] = [1, 2, 3] var wrapped = JX_TypeWrapper(value: array) wrapped.remove(object: 2) wrapped.SELF // [1, 3] 。因此,对于每个HTTP请求,Web应用程序都可以通过设置SCHEMAS来启动请求,从而在PostgreSQL中的数据集之间进行切换,例如:如果是www.my-app.com,则search_path。从应用程序的角度来看,这确实很方便,但是,我认为这与进行连接池的可能性相冲突吗?

问题

因此,在每个HTTP请求中,为整个请求都设置了SET search_path = 'us',并且在该请求中可能有很多个查询到数据库。据我了解,如果我让PGbouncer进行连接池化,则可能会冒一个请求中的第一个查询进入将search_path设置为search_path的连接,而下一个查询则将search_path设置为{ {1}}。

问题

有什么办法可以避免PGbouncer的这种行为?还是我可以用来减少连接开销的替代模式?

1 个答案:

答案 0 :(得分:1)

PostgreSQL Wiki上有一个不错的PgBouncer限制列表。 SET在该列表上。

假设您要在PgBouncer中使用pool_mode = transaction-这是最明智的模式,并且您有一些依赖于会话设置的应用程序代码(例如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

换句话说-要启用事务池,事务必须是 stateless -与HTTP请求的方式完全相同,HTTP请求中包含所有状态信息(以cookie,会话ID等形式)。

很显然,这意味着您需要对应用代码进行修改。在每个调用周围添加一个“包装器”。这很丑陋,如果您必须沿那条路线走,请考虑重写该应用程序以明确使用国家/地区代码作为参数或数据库列。