PGbouncer占用template1连接致无法创建数据库的问题排查与解决
问题描述
在3台PostgreSQL服务器前端部署PGbouncer后,连接池功能运行正常,但执行创建数据库操作时,出现template1被占用、无法创建的错误。通过pg_activity查询发现PGbouncer服务器持有template1的活跃连接,执行SHOW CLIENTS确认无其他外部客户端连接,说明是PGbouncer自身持有该连接;SHOW POOLS结果显示template1存在连接池且有空闲连接:
pgbouncer=# show pools; database | user | cl_active | cl_waiting | cl_active_cancel_req | cl_waiting_cancel_req | sv_active | sv_active_cancel | sv_being_canceled | sv_idle | sv_used | sv_tested | sv_login | maxwait | maxwait_us | pool_mode -----------+-----------+-----------+------------+----------------------+-----------------------+-----------+------------------+-------------------+---------+---------+-----------+----------+---------+------------+----------- pgbouncer | pgbouncer | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | statement root | root | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | session template1 | postgres | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | session (3 rows)
当前PGbouncer配置如下:
pgbouncer.ini ;;; This is an almost minimal starter configuration file that only ;;; contains the settings that are either mandatory or almost always ;;; useful. All settings show their default value. [databases] * = host=localhost port=9999 [pgbouncer] ;; required in daemon mode unless syslog is used ;logfile = ;; required in daemon mode pidfile = /usr/local/pgbouncer/pgbouncer.pid syslog = 1 ;; set to enable TCP/IP connections listen_addr = * ;; PgBouncer port listen_port = 5432 ;; some systems prefer /var/run/postgresql ;unix_socket_dir = /tmp ;; change to taste auth_type = trust ;; probably need this auth_file = /usr/local/pgbouncer/etc/userlist.txt ;; pool settings are perhaps best done per pool ;pool_mode = session ;default_pool_size = 20 ;; should probably be raised for production max_client_conn = 10000 ignore_startup_parameters = extra_float_digits admin_users = pgbouncer,postgres,root
原因分析
- PGbouncer连接池机制:当前template1使用
session池模式,这种模式下客户端断开连接后,PGbouncer会将后端连接保留为空闲状态(sv_idle=1),等待下一个客户端复用,不会立即关闭。 - CREATE DATABASE的排他锁要求:执行
CREATE DATABASE时,PostgreSQL需要对template1获取排他锁(ACCESS EXCLUSIVE),而PGbouncer持有的空闲连接虽无活跃操作,但仍占据着template1的连接,导致无法获取排他锁,从而报错。
解决方法
临时解决:释放template1的空闲连接
登录PGbouncer管理控制台,执行以下命令强制关闭template1池的所有空闲连接:
KILL POOL template1;
执行后再次查询SHOW POOLS,确认template1的sv_idle变为0,此时即可正常执行CREATE DATABASE操作。
长期优化:配置PGbouncer避免占用template1
方法1:禁止PGbouncer池化template1连接
在pgbouncer.ini的[databases]段添加template1的专属配置,将其连接池大小设为0,这样PGbouncer不会为template1创建池化连接,所有连接用完即关:
[databases] * = host=localhost port=9999 template1 = host=localhost port=9999 pool_size=0
修改后重启PGbouncer生效。
方法2:设置空闲连接超时
在pgbouncer.ini的[pgbouncer]段添加server_idle_timeout参数,让空闲连接在指定时间后自动关闭,避免长期占用:
[pgbouncer] server_idle_timeout = 30 # 单位:秒,可根据实际情况调整
修改后重启PGbouncer生效。
操作建议
创建数据库时,建议直接连接到PostgreSQL实例(绕过PGbouncer),这样可以完全避免池化连接的干扰,操作完成后再通过PGbouncer访问业务数据库。
内容的提问来源于stack exchange,提问作者Dan Sherwin
相关产品推荐
相关产品推荐

