通过pgBouncer从Prisma连接Supabase Postgres的连接池问题排查
问题分析与解决方案
核心问题判断
从你描述的现象(pgBouncer角色连接数为0、pg_stat_activity中显示容器IP)可以直接得出:你的应用完全绕过了pgBouncer,直接连接到了Postgres实例,这才导致连接随容器数量线性增长,最终耗尽。
正确使用pgBouncer的预期状态
1. pg_stat_activity 状态
- 所有来自应用的连接,
client_addr字段显示的是Supabase pgBouncer节点的IP(而非你的Cloud Run容器IP) - 连接的
application_name可能会标记为pgBouncer,或保留应用自定义名称,但连接发起方为pgBouncer服务 - 应用角色的连接数会被控制在pgBouncer的池大小范围内(Supabase根据套餐配置,比如免费版默认20),不会随容器数量暴涨
2. Supabase角色连接数
pgBouncer角色的连接数大于0,对应pgBouncer持有的到Postgres的实际物理连接数- 应用角色的连接数远小于Cloud Run容器数量(因为pgBouncer池化了连接,多个容器复用少量物理连接)
排查与修复步骤
1. 彻底校验连接字符串
确认DATABASE_URL完全符合要求:
- 端口必须是
6543(pgBouncer专属端口,而非Postgres默认的5432) - 必须包含
pgbouncer=true参数 - 完整格式示例:
postgres://postgres:YOUR_PASSWORD@db.YOUR_PROJECT.supabase.co:6543/postgres?pgbouncer=true - 检查Cloud Run的环境变量配置,确保部署时没有误用5432端口的连接字符串
2. 调整Prisma连接池配置
在schema.prisma中合理设置连接池大小,避免单个容器的连接数过多:
datasource db { provider = "postgresql" url = env("DATABASE_URL") pool_size = 3 // 根据容器数量和pgBouncer总连接数调整,比如10个容器的话,总连接数不要超过pgBouncer的上限 }
注意:所有容器的Prisma连接池总大小(pool_size × 容器数量)必须小于等于Supabase pgBouncer的最大连接数(可在Supabase「数据库>设置」中查看)
3. 生效配置并验证
- 重启所有Cloud Run容器,确保新的连接字符串和池配置生效
- 重新查询
pg_stat_activity,确认client_addr变为pgBouncer节点IP - 查看Supabase「数据库>角色」页面,确认
pgBouncer角色连接数大于0
4. 额外优化点
- 避免长时持有连接:确保请求处理完成后立即释放连接(Prisma默认自动管理,但手动事务或长耗时查询需注意)
- 若使用Prisma的事务操作,确保遵循pgBouncer的模式限制(Supabase默认使用session模式,兼容性较好;若切换为transaction模式,需避免使用
SET等会话级语句)
内容的提问来源于stack exchange,提问作者sauntimo
相关产品推荐
相关产品推荐

