PgBouncer 参数解释之一 server_reset_query

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 连接池的三种模式。

  1. Session pooling (会话池) : 最为礼貌的方式,当客户端向 pgbouncer 发出连接请求时pgbouncer 将分配连接,
    当客户端断开连接时,Pgbouncer 将连接回收到连接池,session 模式是以客户端
    连接为周期。

  2. Transaction pooling (事务池): 事务池将以事务为周期,当客户端发出事务执行的请求时, pgbouncer 才分分配
    一个连接, 当事务结束时,pgbouncer 将连接回收到连接池。

  3. 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[databases]  
mydb = host=127.0.0.1 dbname=mydb port=1923 pool_size=2
mydb_test = host=127.0.0.1 dbname=mydb_test port=1923 pool_size=2

[pgbouncer]
pool_mode = session
listen_port = 1921
unix_socket_dir = /opt/pgbouncer/etc
listen_addr = *
auth_type = md5
auth_file = /opt/pgbouncer1.4.2/etc/1921/user1921.txt
#logfile = /dev/null
logfile = /var/applog/pgbouncer_log/pgbouncer_1921.log
pidfile = /opt/pgbouncer1.4.2/etc/1921/pgbouncer1921.pid
max_client_conn = 1000
reserve_pool_timeout = 0
admin_users = pgbouncer_admin
stats_users = pgbouncer_guest
ignore_startup_parameters = extra_float_digits
tcp_keepalive = 1
tcp_keepidle = 30
tcp_keepcnt = 3
tcp_keepintvl = 5
server_reset_query=''

备注:这里将 mydb 的pool_size 设置为 2, 是为了后面的测试。同时将参数 pool_mode 设置为 session 模式,server_reset_query 值为空。

Reload pgbouncer

1
2
3
4
5
6
7
[postgres@pgb 1921]$ psql -h 127.0.0.1 -p 1921 pgbouncer pgbouncer_admin  
psql (9.1.0, server 1.4.2/bouncer)
WARNING: psql version 9.1, server version 1.4.
Some psql features might not work.
Type "help" for help.
pgbouncer=# reload;
RELOAD

备注:RELOAD pgbouncer ,使配置生效。

开启 session A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[postgres@pgb load_test]$ psql -h 127.0.0.1 -p 1921 mydb mydb  
psql (9.1.0)
Type "help" for help.
mydb=> show work_mem;
work_mem
----------
1MB
(1 row)
mydb=> set work_mem='2MB';
SET
mydb=> show work_mem;
work_mem
----------
2MB
(1 row)

开启 session B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[postgres@pgb ~]$ psql -h 127.0.0.1 -p 1921 mydb mydb  
psql (9.1.0)
Type "help" for help.
mydb=>
mydb=> show work_mem;
work_mem
----------
1MB
(1 row)
mydb=> set work_mem="3MB";
SET
mydb=> show work_mem;
work_mem
----------
3MB
(1 row)
mydb=>

开启 session C

1
2
3
4
[postgres@pgb ~]$ psql -h 127.0.0.1 -p 1921 mydb mydb  
psql (9.1.0)
Type "help" for help.
mydb=> show work_mem;

备注:当开启 session c 并执行命令时,session C 会处于等侍状态,这是因为配置中已将 mydb 的 poo_size 设置成了 2,最多允许给数据库 mydb 分配两个池子,

结束会话 A

1
mydb=> /q

再次查看会话C

1
2
3
4
5
mydb=> show work_mem;  
work_mem
----------
2MB
(1 row)

备注:在结束会话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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[databases]  
mydb = host=127.0.0.1 dbname=mydb port=1923 pool_size=2
mydb_test = host=127.0.0.1 dbname=mydb_test port=1923 pool_size=2

[pgbouncer]
pool_mode = session
listen_port = 1921
unix_socket_dir = /opt/pgbouncer/etc
listen_addr = *
auth_type = md5
auth_file = /opt/pgbouncer1.4.2/etc/1921/user1921.txt
#logfile = /dev/null
logfile = /var/applog/pgbouncer_log/pgbouncer_1921.log
pidfile = /opt/pgbouncer1.4.2/etc/1921/pgbouncer1921.pid
max_client_conn = 1000
reserve_pool_timeout = 0
admin_users = pgbouncer_admin
stats_users = pgbouncer_guest
ignore_startup_parameters = extra_float_digits
tcp_keepalive = 1
tcp_keepidle = 30
tcp_keepcnt = 3
tcp_keepintvl = 5
server_reset_query = DISCARD ALL

reload pgbouncer

1
2
3
4
5
6
7
[postgres@pgb 1921]$ psql -h 127.0.0.1 -p 1921 pgbouncer pgbouncer_admin  
psql (9.1.0, server 1.4.2/bouncer)
WARNING: psql version 9.1, server version 1.4.
Some psql features might not work.
Type "help" for help.
pgbouncer=# reload;
RELOAD

开启 Session A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[postgres@pgb load_test]$ psql -h 127.0.0.1 -p 1921 mydb mydb  
psql (9.1.0)
Type "help" for help.
mydb=> show work_mem;
work_mem
----------
1MB
(1 row)
mydb=> set work_mem="2MB";
SET
mydb=> show work_mem;
work_mem
----------
2MB
(1 row)
mydb=>

开启 Session B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[postgres@pgb ~]$ psql -h 127.0.0.1 -p 1921 mydb mydb  
psql (9.1.0)
Type "help" for help.
mydb=> show work_mem;
work_mem
----------
1MB
(1 row)
mydb=> set work_mem="3MB";
SET
mydb=> show work_mem;
work_mem
----------
3MB
(1 row)

开启SESSION C

1
2
3
4
[postgres@pgb ~]$ psql -h 127.0.0.1 -p 1921 mydb mydb  
psql (9.1.0)
Type "help" for help.
mydb=> show work_mem;

备注:由于 mydb 库的 poo_size 值为 2, 达到了上限,这里依然是处于 wait 状态。

结束 SESSION A

1
mydb=> /q

查看 SESSION C

1
2
3
4
5
mydb=> show work_mem;  
work_mem
----------
1MB
(1 row)

备注:在结束会话A,再次查看会话C时,这时的 work_mem 值依然为初始值,说明当pgbouncer 在回收 SESSION A 的连接,并将连接分配给 SESSION C 时,将 SESSION A 的 sessoin 级设置的值丢弃了,这也正是因为 server_reset_query 参数设置成 “DISCARD ALL “。

总结

根据上面的实验应该理解 pgbouncer 的参数 server_reset_query 的意思了。

  1. 当 pgbouncer 为 session 模式时,应该将参数值设置 “DISCARD ALL” ,这样当 pgbouncer 回收 连接并分配
    给其它客户端时,之前客户端设置的 session 级别的值将被丢弃,否则将会带来不可控的影响。

  2. 当 pgbouncer 为 Transaction 模式时,由于pgbouncer 连接池的分配是以事务为周期的,当连接池被 pgbouncer
    回收并分配给其它客户端时,session 级别设置的参数将不会保留。所以这个参数可以设置为空。

原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/237814.html

(0)
上一篇 2022年1月29日
下一篇 2022年1月29日

相关推荐

发表回复

登录后才能评论