PgBouncer 1.26.1 配置参数详解
PgBouncer 1.26.1 配置参数全量实测:SHOW CONFIG 98 参数总览、[databases]/[pgbouncer] 段核心参数逐项验证、session/transaction/statement 三池化模式差异实测、RELOAD 在线生效闭环与两套生产配置模板。
PgBouncer 1.26.1 配置参数详解
目标:逐项讲清 PgBouncer 1.26.1 配置文件(pgbouncer.ini)的 [databases] 与 [pgbouncer] 两段核心参数,并以真实环境实测验证参数行为——包括三种池化模式差异、RELOAD 在线生效、连接上限拒绝、空闲连接回收等。文中全部命令与回显均在「Ubuntu 22.04.5 LTS + PgBouncer 1.26.1 + PostgreSQL 18.6 后端」环境实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(pgb-server 10.89.56.3 作为 PgBouncer 服务器,pg18-server 10.89.56.2 作为 PostgreSQL 服务器)
- 系统架构:x86_64
- PgBouncer:1.26.1(源码编译安装于 /usr/local,
--with-systemd;pgbouncer -V回显:libevent 2.1.12-stable / adns: evdns2 / tls: OpenSSL 3.0.2 / systemd: yes) - PostgreSQL:18.6(后端,密码认证 scram-sha-256,业务库 appdb、账号 appuser,密码 q1w2e3r4)
- psql 客户端:psql (PostgreSQL) 14.24 (Ubuntu 14.24-0ubuntu0.22.04.1)
- 配置文件:/etc/pgbouncer/pgbouncer.ini、/etc/pgbouncer/userlist.txt
- 日志/运行目录:/var/log/pgbouncer/、/var/run/pgbouncer/
- 管理控制台入口:
psql -h 127.0.0.1 -p 6432 -U postgres pgbouncer(admin_users 中的用户连接虚拟库 pgbouncer)
二、前置条件
- 已按 《Ubuntu 22.04 安装 PgBouncer 1.26.1 指南》第八章完成基础配置,PgBouncer 处于运行状态:
systemctl is-active pgbouncer
实测回显:
active
- 后端 PostgreSQL 可连通(业务库 appdb 已存在):
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U appuser appdb -c "SELECT 1 AS ok;"
实测回显:
ok
----
1
(1 row)
- 管理控制台可用(本文大量使用):
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U postgres pgbouncer -c "SHOW VERSION;"
实测回显:
version
------------------
PgBouncer 1.26.1
(1 row)
三、参数查看与修改方式
3.1 配置文件结构
pgbouncer.ini 由两类段组成(来源:pgbouncer.org/config.html,查询日期 2026-10-20):
- [databases]:逻辑库名到后端连接信息的映射。行格式为
逻辑库名 = host=... port=... dbname=... [附加参数];连接串里带*时表示"未显式映射的库名全部按此规则透传"。 - [pgbouncer]:全局运行参数。每个参数一行
key = value;多数参数支持运行时修改(changeable=yes),改完 ini 后在管理控制台执行RELOAD即可生效,无需重启。
3.2 SHOW CONFIG:在线查看全部参数
管理控制台的 SHOW CONFIG 一次列出全部参数的当前值、默认值与是否可在线修改:
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U postgres pgbouncer -c "SHOW CONFIG;" | head -12
实测回显(输出节选,全表 98 行参数):
key | value | default | changeable
-----------------------------+--------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+------------
admin_users | postgres | | yes
application_name_add_host | 0 | 0 | yes
auth_dbname | | | yes
auth_file | /etc/pgbouncer/userlist.txt | | yes
auth_hba_file | | | yes
auth_ident_file | | | yes
auth_ldap_options | | | yes
auth_query | SELECT rolname, CASE WHEN rolvaliduntil < now() THEN NULL ELSE rolpassword END FROM pg_authid WHERE rolname=$1 AND rolcanlogin | SELECT rolname, CASE WHEN rolvaliduntil < now() THEN NULL ELSE rolpassword END FROM pg_authid WHERE rolname=$1 AND rolcanlogin | yes
auth_type | scram-sha-256 | md5 | yes
auth_user | | | yes
要点解读:changeable 列为 no 的参数(如 listen_addr、listen_port、pidfile、unix_socket_dir、conffile、pkt_buf 等)只在进程启动时读取一次,修改后必须重启进程;为 yes 的参数修改 ini 后 RELOAD 即时生效。
3.3 RELOAD:在线生效与验证
以 server_idle_timeout 为例演示"改 ini → RELOAD → SHOW CONFIG 确认"的完整闭环。先在 ini 中临时追加(放在 [pgbouncer] 段内任意位置):
server_idle_timeout = 5
执行 RELOAD 并确认新值:
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U postgres pgbouncer -c "RELOAD;"
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U postgres pgbouncer -c "SHOW CONFIG;" | grep server_idle_timeout
实测回显:
RELOAD
server_idle_timeout | 5 | 600 | yes
value 列已变为 5,默认值 600 作为参照保留展示。验证完成后把该行从 ini 删除并再次 RELOAD 恢复默认。
四、参数总览
1.26.1 全部 98 个参数按职能分为九类,各类代表参数如下(完整清单可随时 SHOW CONFIG 获取):
| 分类 | 代表参数 | 说明 |
|---|---|---|
| 监听与并发 | listen_addr、listen_port、max_client_conn、listen_backlog、so_reuseport | 进程入口与客户端总闸 |
| 认证与凭据 | auth_type、auth_file、auth_user、auth_query、auth_hba_file、auth_ldap_options、scram_iterations | 代理层认证体系 |
| 池容量 | default_pool_size、min_pool_size、reserve_pool_size、max_db_connections、max_user_connections、max_db_client_connections、max_user_client_connections | 各维度连接数上限 |
| 池化行为 | pool_mode、server_reset_query、server_check_query、server_check_delay、server_round_robin、query_wait_timeout、query_wait_notify、idle_transaction_timeout、transaction_timeout | 复用与排队行为 |
| 连接生命周期 | server_lifetime、server_idle_timeout、server_connect_timeout、server_login_retry、client_login_timeout、client_idle_timeout、cancel_wait_timeout、autodb_idle_timeout、pool_idle_timeout | 各类超时 |
| 日志与统计 | logfile、syslog、log_connections、log_disconnections、log_pooler_errors、log_stats、stats_period、verbose | 观测面 |
| TLS | client_tls_sslmode、client_tls_ca_file、client_tls_cert_file、client_tls_key_file、server_tls_sslmode、server_tls_protocols、client_tls13_ciphers、server_tls13_ciphers | 双向 TLS |
| DNS | dns_max_ttl、dns_nxdomain_ttl、dns_zone_check_period、resolv_conf | 异步解析调优 |
| 底层与杂项 | pkt_buf、max_packet_size、sbuf_loopcnt、tcp_keepalive 系列、unix_socket_dir、track_extra_parameters、login_notify_message | 协议缓冲与系统参数 |
💡 技术拓展:PgBouncer 的连接数限制是四层漏斗模型,配置时应从外到内协同考虑——
层 参数 默认值 管的是什么 客户端总量 max_client_conn 100 连到 PgBouncer 的 TCP 连接总数(含排队) 每库客户端 max_db_client_connections 0(不限) 单个逻辑库上的客户端总数 每用户客户端 max_user_client_connections 0(不限) 单个数据库用户上的客户端总数 后端物理连接 pool_size / max_db_connections / max_user_connections 20 / 0 / 0 真正打到 PostgreSQL 的连接数 实际生产通常:调大 max_client_conn(如 2000~10000)作为前端总闸,用 pool_size 系参数控制后端物理连接数——这正是连接池的核心价值。
五、[databases] 段参数详解
5.1 基本映射与通配符
本文实测 ini 的 [databases] 段:
[databases]
appdb = host=10.89.56.2 port=5432 dbname=appdb
admindb = host=10.89.56.2 port=5432 dbname=admindb
客户端用 psql ... appdb 连接"逻辑库 appdb",PgBouncer 实际连接 10.89.56.2:5432 上的 appdb 库。SHOW DATABASES 可看到映射结果(实测回显):
name | host | port | database | force_user | pool_size | min_pool_size | reserve_pool_size | server_lifetime | pool_mode | load_balance_hosts | max_connections | current_connections | max_client_connections | current_client_connections | paused | disabled
-----------+-------------+------+-----------+------------+-----------+---------------+-------------------+-----------------+-----------+--------------------+-----------------+---------------------+------------------------+----------------------------+--------+----------
admindb | pg18-server | 5432 | admindb | | 20 | 0 | 2 | 3600 | | | 50 | 0 | 0 | 0 | 0 | 0
appdb | pg18-server | 5432 | appdb | | 20 | 0 | 2 | 3600 | | | 50 | 0 | 0 | 0 | 0 | 0
pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | 0 | 3600 | statement | | 50 | 0 | 0 | 1 | 0 | 0
(3 rows)
(pool_mode 列为空表示跟随全局参数;虚拟库 pgbouncer 本身固定 statement 模式、force_user=pgbouncer,这是管理控制台的固定形态。)
5.2 映射行可用参数
每个 [databases] 映射行可覆盖的全局参数(来源:pgbouncer.org/config.html database 段说明,查询日期 2026-10-20):host、port、dbname、user(force_user)、password、client_encoding、datestyle、timezone、pool_size、min_pool_size、reserve_pool_size、max_connections、server_lifetime、connect_query、pool_mode、load_balance_hosts。
5.3 实测:per-db pool_mode 覆盖
只把 appdb 覆盖为 statement 模式,全局仍是 session——验证"按库差异化池化"。修改映射行:
appdb = host=10.89.56.2 port=5432 dbname=appdb pool_mode=statement
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U postgres pgbouncer -c "RELOAD;"
连 appdb 发起显式事务(实测回显):
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U appuser appdb -c "BEGIN"
FATAL: transaction blocks not allowed in statement pooling mode
连 admindb(未覆盖,全局 session 生效)发起事务(实测回显):
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U postgres admindb -c "BEGIN; SELECT 7 AS tx_ok; COMMIT;"
COMMIT
结论:per-db 参数只影响该库的池,其他库不受影响——同一 PgBouncer 实例可以为"老应用用 session、报表批处理用 transaction、单语句工具用 statement"各配各的。验证后把 pool_mode=statement 从映射行删除并 RELOAD。
六、[pgbouncer] 核心参数分类详解
6.1 监听与并发类
| 参数 | 默认值 | 说明 |
|---|---|---|
| listen_addr | localhost | 监听 IP,多个逗号分隔;0.0.0.0 全网卡。启动期参数 |
| listen_port | 6432 | 监听端口。启动期参数 |
| max_client_conn | 100 | 客户端连接总数上限,超限直接拒绝 |
| listen_backlog | 128 | TCP backlog。启动期参数 |
| so_reuseport | 0 | 多实例监听同一端口做内核负载均衡(1.26 官方推荐的滚动重启基础) |
实测:max_client_conn 超限拒绝。 临时改为 1 并 RELOAD,先占住一个连接,第二个连接被拒:
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U appuser appdb -c "SELECT 2;"
实测回显:
psql: error: connection to server at "127.0.0.1", port 6432 failed: FATAL: no more connections allowed (max_client_conn)
验证后改回 100 并 RELOAD。注意:admin_users 的管理控制台连接不受该限制影响(实测 max_client_conn=1 时管理连接仍可建立,便于容量告急时进控制台排障)。
6.2 认证类
| 参数 | 默认值 | 说明 |
|---|---|---|
| auth_type | md5 | 认证方式:trust/any/md5/scram-sha-256/cert/hba/pam/ldap |
| auth_file | (空) | userlist.txt 路径,格式 "user" "password或secret" |
| auth_user | (空) | auth_query 使用的只读账号(需能查 pg_authid) |
| auth_query | SELECT rolname, ... FROM pg_authid WHERE rolname=$1 AND rolcanlogin | 从后端取密码哈希的查询 |
| auth_hba_file | (空) | pg_hba.conf 风格规则文件(auth_type=hba 时用) |
| scram_iterations | 4096 | 生成 SCRAM secret 的迭代次数(1.25.0 新增,可换认证速度) |
| auth_ldap_options | (空) | LDAP 认证选项(1.25.0+,编译期 --with-ldap) |
本文实测采用 auth_type = scram-sha-256 + auth_file 明文口令形态:PgBouncer 用 userlist.txt 中的明文与客户端完成 SCRAM 握手,再向后端发起独立的 SCRAM 认证。实测链路见第二章第 2 条回显(SELECT 1 成功)。
⚠️ 注意:auth_type=md5 时若后端用户是 SCRAM 存储(PG 14+ 默认),md5 认证链路会失败;PG 18 后端统一用 scram-sha-256 是最省心的选择。
6.3 池容量类
| 参数 | 默认值 | 说明 |
|---|---|---|
| default_pool_size | 20 | 每个「库×用户」池的常规物理连接数 |
| min_pool_size | 0 | 池保底连接数(有客户端连着时才生效) |
| reserve_pool_size | 0 | 突发备用连接数,常规池满且等待超 reserve_pool_timeout 秒后启用 |
| reserve_pool_timeout | 5 | 触发备用池的等待秒数 |
| max_db_connections | 0(不限) | 单个后端数据库的物理连接总数上限(跨池合计) |
| max_user_connections | 0(不限) | 单个用户的物理连接总数上限 |
| max_db_client_connections | 0 | 单库客户端连接上限 |
| max_user_client_connections | 0 | 单用户客户端连接上限 |
| max_prepared_statements | 200 | 协议级 prepared statement 跟踪缓存上限(0 关闭) |
实测:min_pool_size 预建连接。 设 min_pool_size = 5 时,客户端一登录(session 模式),SHOW POOLS 立即出现(实测回显):
appdb | appuser | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 5 | 0 | 0 | 0 | 0 | 0 | session |
即池按保底值预建了 5 条空闲物理连接(sv_idle=5),能消除冷池首查询的建连延迟;代价是后端常驻更多空连接。验证后把 min_pool_size 从 ini 删除并 RELOAD 恢复 0。
6.4 池化行为类(核心)
| 参数 | 默认值 | 说明 |
|---|---|---|
| pool_mode | session | 池化模式:session/transaction/statement(差异实测见第七章) |
| server_reset_query | DISCARD ALL | 连接归还后端的清理语句(transaction/statement 模式默认不执行,由参数跟踪机制替代) |
| server_reset_query_always | 0 | 1 时任何模式都执行 reset_query |
| server_check_query | (空) | 探活查询,1.25.0 起默认发空查询代替 SELECT 1 |
| server_check_delay | 30 | 空闲连接探活周期 |
| server_round_robin | 0 | 1 时多后端主机间轮询分配 |
| query_wait_timeout | 120 | 客户端排队等待物理连接的超时(1.26.0 起可按库/用户覆盖) |
| query_wait_notify | 5 | 排队超过该秒数向客户端发 NOTICE(0 关闭) |
| idle_transaction_timeout | 0 | 事务池模式下客户端 idle-in-transaction 超时秒数 |
| transaction_timeout | 0 | 单个事务最长允许时长(1.25.0 新增) |
| disable_pqexec | 0 | 1 时禁用简单查询协议(防 SQL 注入面) |
实测:query_wait_timeout 场景的可观测面。 PAUSE 期间新查询排队,SHOW POOLS 的 cl_waiting 与 maxwait 直观可见(实测回显,PAUSE appdb 后 2 秒快照):
appdb | appuser | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 1979 | session |
maxwait=2(秒)、maxwait_us=1979(微秒)——这正是容量规划时判断"池是否过小"的关键指标:生产上若 maxwait 长期非零,应优先扩 pool_size 或排查慢事务,而不是无脑调大 query_wait_timeout。
6.5 连接生命周期类
| 参数 | 默认值 | 说明 |
|---|---|---|
| server_lifetime | 3600 | 物理连接最长存活秒数,到期后等事务结束即关闭 |
| server_idle_timeout | 600 | 池内空闲物理连接的存活秒数 |
| server_connect_timeout | 15 | 连后端超时 |
| server_login_retry | 15 | 后端连不上时的重试间隔 |
| client_login_timeout | 60 | 客户端完成登录的超时 |
| client_idle_timeout | 0(不限) | 客户端空闲连接超时(仅登录后空闲) |
| cancel_wait_timeout | 10 | 取消请求等待秒数 |
| autodb_idle_timeout | 3600 | 无人使用的"通配映射库"池的回收秒数 |
| pool_idle_timeout | 0(不限) | 整个池闲置多久后被整体清理(1.26.0 新增;清理会丢失池统计) |
| suspend_timeout | 10 | SUSPEND 等待收尾秒数(1.26.0 起该机制随 takeover 移除而仅余兼容语义) |
实测:server_idle_timeout=5 的回收行为。 改为 5 秒并 RELOAD 后,先制造一条空闲物理连接,1 秒时 sv_idle=1;7 秒后再查已归零(实测回显):
-- 1 秒后 --
appdb | appuser | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | session |
-- 7 秒后 --
appdb | appuser | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | session |
结论:空闲超时回收真实生效。生产取值应大于"应用两次请求的典型间隔",否则物理连接反复重建,反而放大后端负担。
6.6 日志与统计类
| 参数 | 默认值 | 说明 |
|---|---|---|
| logfile | (空,仅 stderr) | 日志文件路径 |
| log_connections / log_disconnections | 1 | 建连/断连留痕 |
| log_pooler_errors | 1 | 池化错误(排队超时、登录失败等)留痕 |
| log_stats | 1 | 按 stats_period 周期输出统计摘要 |
| stats_period | 60 | 统计周期秒数(SHOW STATS 的 avg_* 以此为窗口) |
| verbose | 0 | 运行时日志详细度,可 SET verbose=1 在线调整 |
实测 SET verbose = 1 后控制台返回 SET verbose=1、SET verbose = 0 恢复——排障时可临时打开而不必改 ini 重载。
6.7 TLS 类
| 参数 | 默认值 | 说明 |
|---|---|---|
| client_tls_sslmode | disable | 客户端侧 TLS(disable/allow/require/verify-ca/verify-full) |
| client_tls_ca_file / client_tls_cert_file / client_tls_key_file | (空) | 客户端侧证书链 |
| client_tls_protocols | secure | 客户端侧协议白名单(默认 TLSv1.2+) |
| client_tls13_ciphers / server_tls13_ciphers | (空) | TLS 1.3 套件选择(1.25.0 新增) |
| server_tls_sslmode | prefer | 后端侧 TLS |
| server_tls_ca_file / server_tls_cert_file / server_tls_key_file | (空) | 后端侧证书链 |
| server_tls_protocols | secure | 后端侧协议白名单 |
⚠️ 注意:client_tls_sslmode 默认 disable 意味着"应用 → PgBouncer"这一跳默认明文,跨网段部署必须显式启用并配 verify-full;server_tls_sslmode 默认 prefer 表示后端可用 TLS 时自动加密。1.25.0 起客户端侧还支持 PG 17 的 direct TLS 快速握手。
6.8 DNS 类
| 参数 | 默认值 | 说明 |
|---|---|---|
| dns_max_ttl | 15 | 域名解析缓存秒数 |
| dns_nxdomain_ttl | 15 | NXDOMAIN 缓存秒数 |
| dns_zone_check_period | 0 | SOA 序号周期检查(0 关闭),变化即重解析 |
| resolv_conf | (空) | 指定自定义 resolv.conf |
实测 SHOW DNS_HOSTS 可见解析缓存(回显:hostname pg18-server / ttl 0 / addrs 10.89.56.2:0)——后端按主机名连接时,DNS 故障切换场景(如 RDS 漂移)靠这几个参数控制感知速度。
6.9 底层与杂项类
| 参数 | 默认值 | 说明 |
|---|---|---|
| pkt_buf | 4096 | 包缓冲大小(启动期参数) |
| max_packet_size | 2147483647 | 单包上限;默认值不受 CVE-2026-107348 影响 |
| sbuf_loopcnt | 5 | 单次事件循环内最多转发包数(大查询吞吐相关) |
| track_extra_parameters | (1.26 显示为空) | 额外跟踪的连接参数;1.26.0 起服务端上报参数默认全跟踪,无需手工追加 |
| login_notify_message | (空) | 登录后向客户端发送的 NOTICE 文案(1.26.0 新增,用于明示"你连的是 PgBouncer") |
| application_name_add_host | 0 | 1 时把客户端地址追加到 application_name,便于后端 pg_stat_activity 区分来源 |
| tcp_keepalive / tcp_keepidle / tcp_keepintvl / tcp_keepcnt | 1 / 0 / 0 / 0 | 内核级 TCP 保活 |
| tcp_user_timeout | 0 | TCP 用户超时毫秒数(0 用内核默认) |
| unix_socket_dir | /tmp | Unix socket 目录(启动期参数) |
| unix_socket_mode | 0777 | Unix socket 权限(启动期参数) |
实测:1.26 参数跟踪默认开启的证据。 同一配置在 1.25.2 下 SHOW CONFIG 显示 track_extra_parameters | IntervalStyle(默认追加 IntervalStyle);升级 1.26.1 后同参数默认值变为空——因为 PG 服务端上报的全部参数(含 PG 18 的 search_path、PG 14+ 的 default_transaction_read_only)已默认跟踪(来源:GitHub Releases 1.26.0 Features,实测对照 1.25.2 与 1.26.1 的 SHOW CONFIG,查询日期 2026-10-20)。
七、池化模式差异实测(session / transaction / statement)
本章是池化行为类参数的核心实验:同一套环境,仅切换 pool_mode,观察 SHOW POOLS 中各状态列的变化。实验脚本形态:后台保持一个客户端连接(sleep 管道保持 stdin),期间从管理控制台抓 SHOW POOLS 快照。
7.1 session 模式:客户端在线即独占
pool_mode=session(默认)时,客户端只要连着(哪怕不发任何 SQL),就持有一条物理连接:
appdb | appuser | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | session |
解读:cl_active=1(一个客户端在线),sv_idle=1(一条物理连接已分配给它)。session 模式下"客户端数 ≈ 物理连接数",池化收益最低但兼容性最好。
7.2 transaction 模式:事务外归还
pool_mode=transaction 时,同样"客户端在线但空闲在事务外"的快照:
appdb | appuser | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | transaction |
解读:cl_active=2(两个客户端在线)而 sv_active=0——没有任何一条物理连接被占用,连接已在事务结束时全部归还池中。事务期间再抓快照(客户端执行 BEGIN; SELECT pg_sleep(12); COMMIT;):
appdb | appuser | 2 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 4 | 0 | 0 | 0 | 0 | transaction |
sv_active=1:只有事务真正运行的那 12 秒占住物理连接。这就是 transaction 模式"数百客户端 × 少量后端连接"的机制基础。
transaction 模式下扩展协议的 prepared statement 也能安全使用(1.21+ 的自动跟踪)。实测:transaction 模式下 PREPARE 后跨语句 EXECUTE(psql 两次 -c,物理连接可能已复用他人):
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U appuser appdb -c "PREPARE hello(int) AS SELECT \$1*10; EXECUTE hello(5);"
实测回显:
?column?
----------
50
(1 row)
PgBouncer 在需要时自动向新物理连接重放 PREPARE,应用无感(依赖 max_prepared_statements 跟踪,默认 200)。
7.3 statement 模式:单语句即归还、禁止事务
pool_mode=statement 时,物理连接在每条语句结束后立即归还。单语句正常(实测回显):
ok
----
1
(1 row)
显式事务直接被拒(实测回显):
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 6432 -U appuser appdb -c "BEGIN"
FATAL: transaction blocks not allowed in statement pooling mode
该报错是 statement 模式的标志性边界:它强制 autocommit 语义,适合"单条 SELECT/INSERT 为主"的工具类流量(如监控探针、简单看板),不适合任何事务型应用。
7.4 三模式对比总结
| 观测项 | session | transaction | statement |
|---|---|---|---|
| 客户端空闲时占物理连接 | 占(sv_used/sv_idle 分配给它) | 不占(sv_active=0) | 不占 |
| 事务期间 | 占整个会话时长 | 仅事务运行期占 | 不支持事务 |
| 复用比(客户端:物理) | ≈1:1 | 数百:1 可达 | 最高 |
| BEGIN/COMMIT | 正常 | 正常 | FATAL 拒绝 |
| SET/游标/LISTEN 跨语句 | 安全 | 需依赖参数跟踪(1.26 默认跟踪服务端参数) | 不适用 |
选型建议:生产默认 transaction;老应用会话状态重且无法改造时用 session;探针/单语句工具可 statement。
八、生产配置模板
模板一:OLTP 应用池(16GB 内存 PgBouncer 独立小机,后端 PG 18,数百微服务实例)
[databases]
appdb = host=10.89.56.2 port=5432 dbname=appdb pool_mode=transaction
[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
admin_users = postgres
stats_users = postgres
pool_mode = transaction
max_client_conn = 5000
default_pool_size = 50
min_pool_size = 10
reserve_pool_size = 10
reserve_pool_timeout = 3
max_db_connections = 200
server_lifetime = 3600
server_idle_timeout = 300
query_wait_timeout = 30
idle_transaction_timeout = 60
max_prepared_statements = 200
log_connections = 0
log_disconnections = 0
log_pooler_errors = 1
log_stats = 1
stats_period = 60
logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
unix_socket_dir = /var/run/pgbouncer
适用说明:NVMe SSD 任意容量即可(PgBouncer 几乎无磁盘 IO);内存 512MB 起步绰绰有余;核心思路是"前端总闸 5000,后端物理 200 封顶",等待超时 30 秒快速失败,idle 事务 60 秒强制回收防 vacuum 阻塞。
模板二:保守会话池(老应用强会话依赖,2GB 内存小机)
[databases]
appdb = host=10.89.56.2 port=5432 dbname=appdb pool_mode=session
[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
admin_users = postgres
pool_mode = session
max_client_conn = 300
default_pool_size = 100
server_lifetime = 7200
server_idle_timeout = 600
client_idle_timeout = 1800
log_pooler_errors = 1
logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
unix_socket_dir = /var/run/pgbouncer
适用说明:session 模式复用比≈1:1,max_client_conn 不可虚高(否则失去保护意义);client_idle_timeout 1800 秒清理遗忘的长连接;该形态对后端连接数要求 = 客户端峰值,本质是"限流闸"而非"复用池"。
九、常见问题(FAQ)
Q1:改了 pgbouncer.ini 不生效?
分两类:changeable=yes 的参数需在控制台执行 RELOAD(或 kill -HUP);changeable=no 的参数(listen_addr/listen_port/pidfile/unix_socket_dir/pkt_buf 等)必须重启进程(systemctl restart pgbouncer)。SHOW CONFIG 的 changeable 列是权威依据。
Q2:RELOAD 后已存在的连接会断吗? 不会。RELOAD 只影响新连接的分配与池参数,活动事务不受影响;server_lifetime 缩短等生效也是"温和回收"(事务结束后关闭),不会掐断业务。
Q3:transaction 模式下 SET application_name / search_path 会互相污染吗? 1.26.0 起 PgBouncer 默认跟踪 PostgreSQL 上报的全部连接参数,客户端 SET 后连接归还/再分配时会正确恢复,不再污染下一个客户端(1.25 及以前需要把参数加进 track_extra_parameters 或依赖应用侧每次 SET)。特殊参数仍可通过 track_extra_parameters 显式追加。
Q4:SHOW POOLS 里 maxwait 一直大于 0 怎么办? 说明有客户端在排队等物理连接。先看 sv_active 是否长期顶满 pool_size:是则扩池(default_pool_size)或优化慢事务;偶尔短暂排队(maxwait 秒级)属正常,可用 reserve_pool_size 吸收突发。
Q5:客户端报 FATAL: database "appdb" is disabled / no such database?
前者是控制台执行过 DISABLE appdb(维护窗口用,恢复用 ENABLE appdb);后者是连接串里的库名不在 [databases] 映射里,要么补映射要么改用 * 通配行。
Q6:升级 1.26 后原来用的 SUSPEND 命令报错? 1.26.0 已移除 SUSPEND 与 SHOW FDS(连同 -R takeover 机制),平滑发布请改用 so_reuseport 多实例滚动重启方案。管理命令的完整实测清单见 《PgBouncer 1.26.1 常用 CLI 命令与工具详解》。
十、参考链接
- 官方配置文档:https://www.pgbouncer.org/config.html
- 官方使用文档(池化模式/控制台):https://www.pgbouncer.org/usage.html
- 1.26.0 Release(参数跟踪默认开启等):https://github.com/pgbouncer/pgbouncer/releases/tag/pgbouncer_1_26_0
- 1.26.1 Release:https://github.com/pgbouncer/pgbouncer/releases/tag/pgbouncer_1_26_1
- 本站延伸阅读:《PgBouncer 1.26.1 介绍与选型指南》、《Ubuntu 22.04 安装 PgBouncer 1.26.1 指南》、《PostgreSQL 18 配置参数详解》