PgBouncer 是有用的、重要的,并且充满了危险

这是一篇关于 PostgreSQL 数据库连接池工具 PgBouncer 的详细文章,涵盖了其原理、模式、优缺点及相关注意事项等方面:

  • PgBouncer 简介:它是 PostgreSQL 的轻量级连接池工具,可避免每次连接数据库的开销,有框架级、客户端级和服务器级三种连接池级别。
  • 为何需要 PgBouncer:维护连接有益,PostgreSQL 连接很快变昂贵,一般建议连接数不超过 500,即使有 Postgres 14 中对空闲连接处理的改进,活跃连接仍较昂贵,需要连接池来提高并发性能。
  • PgBouncer 的模式及特点

    • Session 模式:默认且保守,1:1 连接,有助于降低延迟和连接开销,但对提高连接并发能力作用小。
    • Statement 模式:最激进,每条语句后连接回池,失去事务使用能力,仅适用于特殊用例。
    • Transaction 模式:在保持事务的同时提高并发,连接在事务结束后回池,但会改变连接行为,理解和调试较困难。
  • 使用 PgBouncer 的风险(Perils)

    • 检测无效语句:PgBouncer 不分析语句,可能接受不支持的事务模式语句,导致开发者出错,Amazon 的 RDS Proxy 有“连接固定”功能,但也有局限性。
    • 锁超时(SET/RESET)SET lock_timeout在 PgBouncer 连接中不一定有效,可通过绕过 PgBouncer 或使用事务级SET LOCAL来设置锁超时,但并发索引和工具支持存在问题。
    • 语句超时(SET/RESET)SET statement_timeout与 PgBouncer 不兼容,可通过在事务中使用SET LOCAL或按用户设置语句超时,但都有局限性。
    • 透明度:很难确定是否在使用 PgBouncer,尤其在事务模式下,难以保证某些会话功能的正常工作,需要测试和验证设置。
    • Prepared Statements:PgBouncer 文档对预编译语句的说明易引起误解,实际上仅不支持命名预编译语句,可通过协议级预编译计划安全地在事务模式下使用预编译语句。
    • 连接吞吐量/长运行查询:活跃连接对连接池很重要,长运行查询会影响并发,可通过记录慢查询、使用流式查询、设置语句超时和分散读取等方式来防范。
    • Session Level Advisory Locks:会话级锁在 PgBouncer 中工作正常,但在事务模式下存在问题,可使用事务级锁或保持单独的直接连接到 Postgres 来解决。
    • Listen/NotifyLISTEN/NOTIFY在事务模式下不完全支持,NOTIFY可在事务模式下工作,使用LISTEN/NOTIFY时需确保连接到 Postgres。
    • 单线程:PgBouncer 运行在单个进程和线程中,最多利用一个 CPU 核心,可通过负载均衡 PgBouncer 实例来解决。
    • pg_dump:在 PgBouncer 上运行pg_dump可能出错,应使用直接连接到 Postgres 进行备份操作。
    • 其他不可用的功能:一些功能在事务模式下不兼容,如WITH HOLD CURSOR、临时表的相关操作和LOAD语句等。
  • 应对措施及建议

    • Linting:目前缺乏自动检测 PgBouncer 问题的工具,可通过发布实验性 gem 等方式来提高安全性。
    • 改进 Postgres 连接处理:Postgres 14 有关于快照可扩展性的改进,提高了连接效率,但大部分工作仍集中在构建更好的连接池工具。
  • PgBouncer 替代品:Supavisor、PgCat、Odyssey、Pg Pool II 和 RDS Proxy 等工具都有事务模式的局限性,各有优势。

总之,Postgres 很棒,PgBouncer 很重要,使用时要了解其潜在问题并采取相应措施。

阅读 565
0 条评论