Pgbouncer 有个重要参数为 server_reset_query ,这个参数可以控制 pgbouncer 连接池复用的行为,起初对这个参数的意思感到非常的不理解,今天做了下实验,总算对这个参数明白一二。
手册上的解释
手册上 server_reset_query 的参数解释如下:
Query sent to server on connection release, before making it available to other clients. At that moment no transaction is in progress so it should not include ABORT or ROLLBACK.
A good choice for Postgres 8.2 and below is:
server_reset_query = RESET ALL; SET SESSION AUTHORIZATION DEFAULT;for 8.3 and above its enough to do:
server_reset_query = DISCARD ALL;When transaction pooling is used, the server_reset_query should be empty, as clients should not use any session features.
Default: DISCARD ALL
备注:手册上的这段话之前看过很多次,一直没怎么懂,只知道当 pgbouncer 的 pool_mode 设置为 session 模式时,建议将server_reset_query 设置成 “DISCARD ALL”,当 pgbouncer 的 pool_mode 设置为 transaction 时,这个参数应该设置成空,即 server_reset_query=’’, 在实验之前,先来看下 pgbouncer 的三种模式。
PgBouncer 的三种模式
首先看看 pgbouncer 连接池的三种模式。
-
Session pooling (会话池) : 最为礼貌的方式,当客户端向 pgbouncer 发出连接请求时pgbouncer 将分配连接,
当客户端断开连接时,Pgbouncer 将连接回收到连接池,session 模式是以客户端
连接为周期。 -
Transaction pooling (事务池): 事务池将以事务为周期,当客户端发出事务执行的请求时, pgbouncer 才分分配
一个连接, 当事务结束时,pgbouncer 将连接回收到连接池。 -
Statement pooling ( 语句池): 语句池是最为激进的模式,当客户端一条语句执行完时, pgbouncer 会立即将连接
回收到连接池,所以含有多个语句的事务不能在这种模式下运行,因为事务的连接
会被中断。
当pgbouncer 模式为 session 时,建议将 server_reset_query 设置成 “DISCARD ALL” ,为了理解这个参数下面做了两个实验说明下。
场景一: server_reset_query=’’
当server_reset_query 设置为 ‘’ 时,编写 config1921.ini ,设置 server_reset_query, pool_mode 参数。
config1921.ini 文件配置
1 |
[databases] |
备注:这里将 mydb 的pool_size 设置为 2, 是为了后面的测试。同时将参数 pool_mode 设置为 session 模式,server_reset_query 值为空。
Reload pgbouncer
1 |
[postgres@pgb 1921]$ psql -h 127.0.0.1 -p 1921 pgbouncer pgbouncer_admin |
备注:RELOAD pgbouncer ,使配置生效。
开启 session A
1 |
[postgres@pgb load_test]$ psql -h 127.0.0.1 -p 1921 mydb mydb |
开启 session B
1 |
[postgres@pgb ~]$ psql -h 127.0.0.1 -p 1921 mydb mydb |
开启 session C
1 |
[postgres@pgb ~]$ psql -h 127.0.0.1 -p 1921 mydb mydb |
备注:当开启 session c 并执行命令时,session C 会处于等侍状态,这是因为配置中已将 mydb 的 poo_size 设置成了 2,最多允许给数据库 mydb 分配两个池子,
结束会话 A
1 |
/q |
再次查看会话C
1 |
mydb=> show work_mem; |
备注:在结束会话A后,会话 c的 “ show work_mem” 命令等侍消失,并且显示值为 2MB。因为将会话 A结束时, pgbouncer 将连接回收到连接池中并分配给了会话C,此时并没有清除会话A设置的 session 级属性。所以在会话C 看到的是会话A设置的参数。
场景二: server_reset_query = DISCARD ALL
当 server_reset_query 设置为 ‘DISCARD ALL’时 ,看下情况。将参数 server_reset_query 设置成 “DISCARD ALL”
config1921.ini 配置
1 |
[databases] |
reload pgbouncer
1 |
[postgres@pgb 1921]$ psql -h 127.0.0.1 -p 1921 pgbouncer pgbouncer_admin |
开启 Session A
1 |
[postgres@pgb load_test]$ psql -h 127.0.0.1 -p 1921 mydb mydb |
开启 Session B
1 |
[postgres@pgb ~]$ psql -h 127.0.0.1 -p 1921 mydb mydb |
开启SESSION C
1 |
[postgres@pgb ~]$ psql -h 127.0.0.1 -p 1921 mydb mydb |
备注:由于 mydb 库的 poo_size 值为 2, 达到了上限,这里依然是处于 wait 状态。
结束 SESSION A
1 |
/q |
查看 SESSION C
1 |
mydb=> show work_mem; |
备注:在结束会话A,再次查看会话C时,这时的 work_mem 值依然为初始值,说明当pgbouncer 在回收 SESSION A 的连接,并将连接分配给 SESSION C 时,将 SESSION A 的 sessoin 级设置的值丢弃了,这也正是因为 server_reset_query 参数设置成 “DISCARD ALL “。
总结
根据上面的实验应该理解 pgbouncer 的参数 server_reset_query 的意思了。
-
当 pgbouncer 为 session 模式时,应该将参数值设置 “DISCARD ALL” ,这样当 pgbouncer 回收 连接并分配
给其它客户端时,之前客户端设置的 session 级别的值将被丢弃,否则将会带来不可控的影响。 -
当 pgbouncer 为 Transaction 模式时,由于pgbouncer 连接池的分配是以事务为周期的,当连接池被 pgbouncer
回收并分配给其它客户端时,session 级别设置的参数将不会保留。所以这个参数可以设置为空。
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/237814.html