Pgpool-II 4.7.3 配置参数详解
Pgpool-II 4.7.3 pgpool.conf 核心参数逐项实测详解:连接池排队、负载均衡路由判定、memqcache 命中率、健康检查摘除恢复、4.7 watchdog 新配置全链路、在线恢复四坑,全部真实回显(实测日期 2026-10-20)。
Pgpool-II 4.7.3 配置参数详解
目标:本篇是 Pgpool-II 4.7.3 的配置实战篇——对 pgpool.conf 核心参数逐项展开,每一项关键行为都给出在真实多机环境中的实测结果与原始回显,覆盖连接池、负载均衡、内存缓存、健康检查、4.7 全新 watchdog 高可用与在线恢复六大主题,并沉淀避坑清单。
一、实测环境与配置文件总览
1.1 实测环境
| 角色 | 系统/版本 | 地址 | 说明 |
|---|---|---|---|
| pgpool 主机 | Ubuntu 22.04,pgpool2 4.7.3-1.pgdg22.04+1(PGDG apt) | 10.89.58.7 | systemd 管理(pgpool2.service),监听 9999/9898 |
| PostgreSQL 主库 pg1 | PostgreSQL 17.11(Alpine 官方镜像部署形态) | 10.89.58.2 | primary,5432 |
| PostgreSQL 备库 pg2 | PostgreSQL 17.11(Alpine 官方镜像部署形态) | 10.89.58.3 | standby,5432,流复制 |
高可用扩展实验另引入第二台 pgpool 主机 10.89.58.4(watchdog 对端),VIP 为 10.89.58.100。全部实测日期为 2026-10-20。
1.2 配置文件位置
| 安装方式 | 路径 |
|---|---|
| PGDG apt(Ubuntu/Debian) | /etc/pgpool2/pgpool.conf(模板在 /usr/share/pgpool2/pgpool.conf.sample) |
| 源码 make install | <prefix>/etc/pgpool.conf(来自 src/sample/pgpool.conf.sample-*) |
| rpm/yum | /etc/pgpool-II/pgpool.conf |
4.7.3 提供多份模板:pgpool.conf.sample(全参数注释)、pgpool.conf.sample-stream(流复制起步)、pgpool.conf.sample-replication、pgpool.conf.sample-raw、pgpool.conf.sample-logical、pgpool.conf.sample-watchdog。生产起步推荐复制 sample-stream 再改。
1.3 语法红线
pgpool.conf 的字符串值必须用单引号,双引号会直接 FATAL:
2026-10-19 16:4x ERROR: failed to read the configuration file. syntax error: "load_balance_mode = "on""
实测时误用双引号后 pgpool 拒绝启动,改为单引号 load_balance_mode = 'on' 立即恢复正常。修改后生效方式两选一:systemctl reload pgpool2(对应 PCP 命令见本专栏命令篇)热加载多数参数,或 systemctl restart pgpool2 冷重启(连接、内存缓存清空)。
二、连接与进程参数
2.1 监听参数
listen_addresses = '*'
port = 9999
pcp_listen_addresses = '*'
pcp_port = 9898
unix_socket_directories = '/var/run/postgresql'
port 是前端应用的连接入口,pcp_port 是运维接口入口(认证来自 pcp.conf)。实测 ss -tlnp | grep -E '9999|9898' 可见 pgpool 进程同时监听两个端口。
2.2 连接池规模
| 参数 | 默认 | 实测取值 | 语义 |
|---|---|---|---|
| num_init_children | 32 | 16(排队实验临时改为 2) | 预启动的 pgpool 子进程数 = 最大并发前端连接数 |
| max_pool | 4 | 4 | 每个子进程缓存的后端连接数(按 database:user 对复用) |
| child_life_time | 300s | 300 | 子进程空闲寿命,到期自杀重生防内存泄漏 |
| connection_life_time | 0 | 0 | 缓存的后端连接空闲多久断开 |
| child_max_connections | 0 | 0 | 子进程处理满 N 个连接后重生(0 关闭) |
| reserved_connections | 1 | 1 | 超级用户预留槽(非 superuser 占满时仍可进入) |
排队实测:临时将 num_init_children 改为 2 并重启,三个并行 psql -c "select 1" 会话,第三个会话在前两个持连期间阻塞,实测等待 6.025 秒后返回(前一个会话结束释放子进程)。show pool_processes 可直观看到子进程 total_processes = 2 与各进程的 database/user 占用,排队场景正是多数「报错 pool 吧连接占满」问题的根源——容量规划按 num_init_children × max_pool 估算后端总连接数,且不要超过后端 max_connections 减去复制与运维预留。
2.3 show pool_pools:池内连接明细
pool_pid | start_time | backend_id | hostname | port | status | pool_counter | pool_pid=子进程
---------+---------------------+------------+----------+------+--------+--------------+
12345 | 2026-10-20 09:00:01 | 0 | pg1 | 5432 | 1 | 3 |
12345 | 2026-10-20 09:00:01 | 1 | pg2 | 5432 | 1 | 8 |
pool_counter 是该槽被复用次数,status 1 为连接中。max_pool 按「database + user」维度分槽,同一子进程内不同库/用户各占一槽,这是「连接数暴涨」排查时最容易被忽略的乘法因子。
三、后端与集群模式参数
3.1 backend_clustering_mode(4.7 新)
backend_clustering_mode = 'streaming_replication'
这是 4.7.0 引入的集群模式总开关,取值 streaming_replication(默认)/ logical_replication / raw / slony。4.7 正式退役 Slony 模式(参数仅保留兼容,官方公告见 4.7.0 Release Notes)。同时 4.7 移除了 master_slave_mode 与 master_slave_sub_mode:流复制语义并入 backend_clustering_mode,实测旧配置写 master_slave_mode = 'on' 会得到 FATAL unknown parameter。老配置迁移时直接删掉这两个参数即可。
3.2 后端定义
backend_hostname0 = 'pg1'
backend_port0 = 5432
backend_weight0 = 0
backend_flag0 = 'ALLOW_TO_FAILOVER'
backend_hostname1 = 'pg2'
backend_port1 = 5432
backend_weight1 = 1
backend_flag1 = 'ALLOW_TO_FAILOVER'
要点:
- 编号从 0 开始,必须连续;hostname 可写主机名(依赖 DNS)或 IP,实测自定义主机名与 IP 均可正常解析接入;
backend_weightN只影响读请求的分配比例,主库写请求不受权重控制;backend_flagN取值ALLOW_TO_FAILOVER/DISALLOW_TO_FAILOVER,后者常用于临时屏蔽某节点的自动摘除。
3.3 流复制检查
sr_check_period = 10
sr_check_user = 'postgres'
sr_check_database = 'postgres'
sr_check_password = ''
delay_threshold = 0
pgpool 以 sr_check_user 周期查询备库 pg_stat_wal_receiver 等判断复制状态;delay_threshold 按字节数延迟阈值把读请求暂时路由回主库(0 = 不启用)。
四、负载均衡参数(实测)
4.1 核心开关
load_balance_mode = 'on'
read_only_function_list = 'count,inet_server_addr'
write_function_list = ''
4.2 路由实测:weight 0/1 与 select_cnt
配置主库权重 0、备库权重 1 后,多次执行 SELECT inet_server_addr() 定位实际执行节点,回显始终为备库地址 10.89.58.3;show pool_nodes 中备库 select_cnt 持续增长而主库保持,证实读流量按权重全量落到备库。inet_server_addr() 与 count() 已加入 read_only_function_list,因此函数调用也被判定为可负载均衡。
4.3 系统表查询硬编码走主库(源码级判定)
实测发现:即使开启 LB 且权重全给备库,select * from pg_catalog.pg_class limit 1 这类系统表查询始终命中主库(inet_server_addr() 返回主库地址)。这在 4.7.3 源码 src/context/pool_query_context.c 中有明确注释——包含系统目录(system catalogs)的 SELECT 被标记为不可负载均衡,因为目录状态以主库为准。排查「为什么这条 SELECT 没走备库」时先查是不是系统表。
4.4 函数路由规则(4.7 新参数)
4.7.0 用 read_only_function_list / write_function_list 取代了旧参数 white_function_list / black_function_list,旧名实测已不被识别。语义变化:
| 情形 | 路由行为 |
|---|---|
| 仅配 read_only_function_list | 名单内函数走备库,名单外按默认策略(视为主库) |
| 仅配 write_function_list | 名单内函数强制主库,其余按 pg_proc 易变性判定 |
| 两者皆空(默认) | 逐函数查 pg_proc.provolatile:IMMUTABLE/STABLE 可 LB,VOLATILE 走主库 |
| 函数不在 pg_proc | 无法判定,走主库 |
注意两个隐含规则(源码与日志双证):显式事务(BEGIN...COMMIT)内的所有语句不参与 LB,一律发往当前主库以保证一致性;SELECT ... FOR UPDATE 等锁定读也走主库。
五、内存缓存参数(实测)
memory_cache_enabled = 'on'
memqcache_method = 'shmem'
memqcache_total_size = 64MB
memqcache_max_num_cache = 1000000
memqcache_cache_block_size = 1MB
memqcache_expire = 0
memqcache_auto_cache_invalidation = 'on'
memqcache_maxcache = 40kB
memqcache_method取值shmem(默认,共享内存)或memcached;memqcache_maxcache(默认 40kB)是单条结果集缓存上限,超过则不缓存,结果集偏大的业务需调大,同时注意其应小于memqcache_cache_block_size;- 缓存 key 是「协议层消息 + 数据库 OID」摘要,DML 会按表 OID 自动失效(
memqcache_auto_cache_invalidation = on)。
命中率实测:同一查询执行三次后查看 show pool_cache:
cache_hit_ratio | num_cache_hits | num_selects | cache_storage |...
0.67 | 2 | 1 | shmem |
两次命中一次回源(hits=2 / selects=1),符合首轮 miss、后续 hit 的预期。绕过缓存的手段:/* NO QUERY CACHE */ 注释、临时函数或写会话。更新缓存后如需强制清空,可执行 pcp_invalidate_query_cache(本专栏命令篇有实测)。
六、健康检查与故障切换(实测)
6.1 参数组
health_check_period = 10
health_check_timeout = 20
health_check_user = 'postgres'
health_check_database = 'postgres'
health_check_max_retries = 3
health_check_retry_delay = 1
connect_timeout = 10000
search_primary_node_timeout = 300
failover_command = ''
follow_primary_command = ''
health_check_period:检测周期(秒),0 = 关闭;health_check_max_retries × (health_check_timeout + health_check_retry_delay)决定摘除前的总容忍时长,网络抖动场景要给出重试余量,避免「闪断即摘除」;failover_command在节点被判定故障后执行(典型用法是触发 VIP 迁移或原主库隔离),follow_primary_command在新主确立后对剩余备库执行重新指向。
6.2 摘除与恢复实测
停止 pg2 的 PostgreSQL 进程后,10 秒周期内健康检查判定失败,show pool_nodes 中 pg2 状态转为 down/down,读流量随之全部回落主库(lb_weight 1 失效);随后重启 pg2 的 PostgreSQL,pgpool 不会自动把 down 节点拉回池内,必须执行 pcp_attach_node(实测回执 pcp_attach_node -- Command Successful,随后 show pool_nodes 显示 pg2 恢复 up/up)。pcp_health_check_stats 命令可查看最近一轮健康检查的耗时与结果明细(命令篇实测)。
七、watchdog 高可用参数(4.7 重构实测)
4.7 对 watchdog 配置做了一次不兼容重构,旧 4.x 模板直接套用会连环报错。以下按「多机双节点 + 心跳 + VIP」目标形态给出实测可运行配置(两台 pgpool 主机 10.89.58.7 与 10.89.58.4,VIP 10.89.58.100)。
7.1 节点标识(必须)
use_watchdog = 'on'
wd_hostname = '10.89.58.7'
wd_port = 22200
并在每台主机建立节点编号文件(4.7 强制):
echo 0 > /etc/pgpool2/pgpool_node_id # 10.89.58.7 上
echo 1 > /etc/pgpool2/pgpool_node_id # 10.89.58.4 上
实测教训:缺少该文件时 pgpool 直接 FATAL watchdog: node id file is not found;编号必须与 hostname0/1 声明顺序对应,且 hostnameN 列表必须包含本机,否则报 no watchdog configuration for local pgpool node。
7.2 集群模式与心跳
backend_clustering_mode = 'streaming_replication'
delegate_ip = '10.89.58.100'
heartbeat_hostname0 = '10.89.58.7'
heartbeat_port0 = 9694
heartbeat_device0 = 'eth0'
heartbeat_hostname1 = '10.89.58.4'
heartbeat_port1 = 9694
heartbeat_device1 = 'eth0'
实测确认的四个硬约束:
- 心跳声明必须覆盖自身索引(0 号机也写 heartbeat_hostname0),漏掉报
no heartbeat interfaces defined; heartbeat_deviceN不可为空(绑定收发网卡用于校验);if_cmd_path/arping_path在 4.7 收敛为单目录(不再是带命令名的完整路径):Debian/Ubuntu 写/usr/sbin,若ip/arping实际位于/usr/bin,可用软链接对齐;wd_heartbeat_keepalive(默认 2s)/wd_heartbeat_deadtime(默认 30s)决定脑裂判定速度。
7.3 仲裁与半数投票
wd_lifecheck_method = 'heartbeat'
enable_consensus_with_half_votes = 'on'
wd_priority = 10 # 10.89.58.7 上;对端配 1
两节点集群默认需要严格多数派,任一台宕机后幸存节点票数不足而无法接管 VIP。实测设置 enable_consensus_with_half_votes = 'on' 后,LEADER 宕机时 STANDBY 以半数票直接升级为 LEADER 并挂载 VIP(约一个 deadtime 周期内完成),旧 LEADER 恢复后以 STANDBY 重新入队——全程无人工干预。wd_priority 在票数相同时决定谁优先成为 LEADER。
7.4 运行验证
show watchdog(SQL)或 pcp_watchdog_info 可观察 LEADER/STANDBY/DEAD 与 VIP 持有者;接管期间用 ip addr show eth0 能看到 eth0:0 上的 10.89.58.100/24 挂载与摘除。VIP 的 ARP 通告依赖 arping_path 指向的 arping 程序,权限上挂载/摘除需要 root 能力(systemd 单元下以 root 运行 pgpool 是常见做法)。
八、在线恢复参数(四坑实测)
8.1 参数组
recovery_user = 'postgres'
recovery_1st_stage_command = 'recovery_1st_stage'
pcp_recovery_node 触发时,pgpool 连接主库执行 pgpool_recovery() 函数,函数在主库 PGDATA 下查找并执行 1st stage 脚本(参数固定顺序:主库 PGDATA、目标主机、目标 PGDATA、主库端口、目标节点号、目标端口、主库主机),完成后自动查找执行 pgpool_remote_start(约定文件名,不占参数位)。前置条件:
- 主库安装
pgpool_recovery扩展(源码src/sql/pgpool-recovery,PGXS 编译,make USE_PGXS=1 install后CREATE EXTENSION pgpool_recovery); - 主库 PGDATA 下部署
recovery_1st_stage与pgpool_remote_start(官方样例在src/sample/,需按实际 PGHOME/SSH 路径改写,chmod 755); - 主库到备库的 postgres 系统用户免密 SSH(专用密钥
id_rsa_pgpool放/var/lib/postgresql/.ssh/); - 恢复目标节点的 PostgreSQL 已停止。
8.2 成功序列实测
实测环境(PG17,PGHOME=/usr/local,备库 10.89.58.3)三轮执行 pcp_recovery_node -h 127.0.0.1 -p 9898 -U admin -n 1:
pcp_recovery_node -- Command Successful
node_id | hostname | port | status | pg_status | role | pg_role | replication_delay
0 | pg1 | 5432 | up | up | primary | primary |
1 | pg2 | 5432 | up | up | standby | standby | 0
备库 pg.log 关键回显:entering standby mode → consistent recovery state reached → started streaming WAL from primary。恢复脚本内含物理复制槽创建(以目标主机名命名),全程无需手工 pg_basebackup。
8.3 四个真实坑点(后端为 Alpine 系统或官方发行版镜像部署形态时)
以下坑点在 2026-10-20 实测中逐一踩中,若你的 PG 节点是传统 systemd 包部署可跳过本节:
- 账户锁定:Alpine 下 postgres 账户
/etc/shadow密码字段默认!,OpenSSH 视为 locked,任何认证方式都拒绝,sshd 调试日志表现为User postgres not allowed because account is locked。修复:字段改为*(保留锁定密码登录但放行密钥认证)。 - StrictModes 拒读 authorized_keys:数据目录父级
/var/lib/postgresql默认 1777(粘滞位全可写),sshd 报Authentication refused: bad ownership or modes for directory /var/lib/postgresql。修复:chown postgres:postgres+chmod 755。 - VOLUME 挂载点不可删:官方发行版镜像将 PGDATA 声明为数据卷挂载点,恢复脚本样例中
rm -rf $PGDATA报Resource busy。修复:改为清空内容——find "$PGDATA" -mindepth 1 -delete。 - PGDATA 权限:pg_basebackup 向既有目录写入后目录权限仍为 1777,postmaster 启动 FATAL
data directory has invalid permissions ... should be u=rwx (0700) or u=rwx,g=rx (0750)。修复:脚本在 pg_basebackup 后追加chmod 700 $PGDATA。
8.4 detach 不停库的次生坑
实测确认:pcp_detach_node 只把节点移出 pgpool 池(status 变 down,pg_status 仍 up),不会停止节点上的 PostgreSQL。对这样的节点直接执行 pcp_recovery_node,1st stage 会清空并重建其 PGDATA(旧进程的 pid 文件被删),随后 remote_start 的 pg_ctl 判断「未运行」尝试启动,但 5432 端口仍被旧进程占用,最终报 executing remote start failed。正确顺序:先停节点 PostgreSQL,再 pcp_detach_node(或依赖健康检查摘除),再 pcp_recovery_node。恢复完成后若节点未自动入池,补一次 pcp_attach_node。
九、认证与安全参数
9.1 三份凭据文件
| 文件 | 内容 | 实测格式 |
|---|---|---|
| pcp.conf | PCP 接口账号 | admin:c62d929e7b7e7b6165923a5dfc60cb56,为 md5(密码) 裸哈希无前缀(与 pool_passwd 的「带 md5 前缀且加盐用户名」不同,源码 src/tools/pcp/ 实证) |
| pool_passwd | 前端到后端的密码映射 | appuser:AESWQ2KKG1ntHerL+GsZtGpEw==(AES-256-CBC)或 user:md5...(md5(密码+用户名)) |
| pool_hba.conf | 前端接入 ACL | 语法同 pg_hba.conf,trust/md5/scram 等 |
.pcppass 口令文件为 4 段式 hostname:port:username:password(通配用 *),文件权限必须 600——实测写成 5 段式时会把第 4、5 段整体当密码导致 PCP 连续认证失败。pgpool 主进程需要对 pcp.conf、pool_passwd 有读权限,apt 安装后默认属主 root:postgres 即可。
9.2 pg_enc:AES 加密 pool_passwd
openssl rand -hex 32 > /etc/pgpool2/pool_key && chmod 600 /etc/pgpool2/pool_key
pg_enc -m -u appuser -k /etc/pgpool2/pool_key -f /etc/pgpool2/pgpool.conf 'secret123'
# 输出:appuser:AESWQ2KKG1ntHerL+GsZtGpEw==
pg_enc -k /etc/pgpool2/pool_key 'secret123' # 不带 -m 时仅打印密文
实测确认:key 文件为 hex 编码(openssl rand -hex 32 产出 64 位十六进制串);-m 直接把 AES 前缀密文写入 pgpool.conf 中 pool_passwd 指定的文件;后端认证要求为 md5/scram-sha-256 时 pool_passwd 内必须存在对应用户条目,否则后端拒绝。
9.3 TLS
ssl = 'on' + ssl_key/ssl_cert/ssl_ca_cert 一组参数控制前端 TLS;后端方向走 PostgreSQL 自身的 ssl 配置,pgpool 透明转发。
十、日志参数(4.7 变更)
log_destination = 'stderr'
logging_collector = 'on'
log_directory = '/var/log/pgpool'
log_filename = 'pgpool-%Y-%m-%d.log'
work_dir = '/var/log/pgpool'
4.7.0 将旧参数 logdir 更名为 work_dir(存放状态文件:pgpool_status、pgpool.pid 等),旧名实测报 unknown parameter。开启 logging_collector 后 pgpool 才会把 stderr 重定向为按日轮转的文件;实测 pcp_log_rotate 在 collector 关闭时返回 logging_collector disabled(命令篇有原始回执),属于预期行为而非故障。
十一、核心参数速查表
| 参数 | 默认 | 生产建议 | 备注 |
|---|---|---|---|
| num_init_children | 32 | 按峰值并发 ÷ 复用率 | 排队实测见 §2.2 |
| max_pool | 4 | 2-4 | 与后端 max_connections 相乘 |
| backend_weightN | 1 | 主库 0(读写分离时) | 只影响读 |
| load_balance_mode | on | on | 系统表/事务例外见 §4.3 |
| memory_cache_enabled | off | 视热点读比例 | §5 |
| health_check_period | 0 | 10 | 0 = 关闭,务必开启 |
| backend_clustering_mode | streaming_replication | streaming_replication | 4.7 新,取代 master_slave_mode |
| read_only_function_list | 空 | count 等只读函数 | 4.7 新,取代 white_function_list |
| enable_consensus_with_half_votes | off | 双节点时 on | §7.3 |
| recovery_1st_stage_command | 空 | recovery_1st_stage | 配套脚本见 §8 |
| work_dir | /var/log/pgpool | — | 4.7 由 logdir 更名 |
十二、FAQ 与避坑清单
- 改了配置不生效:先确认 reload 还是 restart 生效域;
show pool_status可核对运行时值。 - SELECT 没走备库:系统表查询、显式事务、VOLATILE 函数、锁定读四类例外(§4.3/§4.4)。
- 连接数超限:
num_init_children × max_pool加复制/运维连接别超后端 max_connections;第三个连接排队 6 秒的实测见 §2.2。 - watchdog 起不来:按 §7.1-§7.3 四个硬约束逐项核对(pgpool_node_id 文件、hostnameN 含自身、heartbeat 覆盖自身索引、device 非空)。
- 在线恢复 remote_start 失败:detach 不停库 + 端口占用(§8.4);Alpine 部署形态四坑(§8.3)。
- pcp 认证失败:pcp.conf 用
md5(密码)裸哈希;.pcppass四段式且 chmod 600(§9.1)。 - pgpool 拒绝启动报语法错误:字符串一律单引号(§1.3)。
- 升级到 4.7:master_slave_mode 删除、logdir→work_dir、white/black_function_list 更名,三处参数迁移(§3.1/§4.4/§10)。
十三、参考链接
- 官方配置文档(4.7.3):https://www.pgpool.net/docs/latest/en/html/runtime-config.html
- watchdog 配置:https://www.pgpool.net/docs/latest/en/html/runtime-watchdog.html
- 在线恢复:https://www.pgpool.net/docs/latest/en/html/online-recovery.html
- watch_dog 样例模板:https://www.pgpool.net/docs/latest/en/html/example-watchdog.html
- 4.7.0 Release Notes(参数迁移清单):https://www.pgpool.net/docs/latest/en/html/release-4-7-0.html
- PCP 命令参考:https://www.pgpool.net/docs/latest/en/html/pcp-commands.html
- 本专栏同族文档:《Pgpool-II 4.7.3 介绍与选型指南》、《Ubuntu 22.04 安装 Pgpool-II 4.7.3 指南》、《Pgpool-II 4.7.3 常用 CLI 命令与工具详解》