连接池

PolarDB支持会话级连接池和事务级连接池,您可以根据业务场景选择合适的连接池,帮助降低因大量连接导致的数据库负载压力。

注意事项

  • 更改连接池设置后,仅对新建连接生效。如何修改连接池设置,请参见配置数据库代理

  • 当前连接池功能不支持同一个账号对不同IP有不同的权限。如果您为同一个账号的不同IP设置了不同的库或者表权限,开通连接池可能会导致权限错误问题。例如,user@192.xx.xx.1设置了database_a的权限,而user@192.xx.xx.2没有database_a的权限,可能会导致连接复用时权限出错。

  • 如果业务频繁使用COM_STATISTICS命令时,不建议启用连接池功能。该命令在数据库上的实现是先进行上锁,然后再遍历所有连接。而开启连接池功能是将短连接转变为长连接,这可能会导致长连接的数量增加,从而触发该命令的瓶颈,进而导致性能下降。同时建议非必要情况下,尽量减少对该命令的调用,频繁调用会造成严重的性能下降,进而影响整体业务的响应时间。

  • 本文介绍的功能是PolarDB数据库代理的连接池功能。该功能并不影响客户端的连接池功能,如果客户端已经支持连接池,则可以不使用PolarDB数据库代理的连接池功能。

会话级连接池

  • 工作原理2

    会话级连接池用于减少短连接业务频繁建立新连接导致MySQL负载高。当您的连接断开时,系统会判断当前的连接是否是一个闲置的连接,如果是闲置连接,系统将会代理该连接并保留在连接池中一小段时间,如果这时新的连接建立的话就会直接从连接池里获得连接(命中的条件包括userclientipdbname等),从而减少与数据库的建连开销。如果没有可用的连接,则走正常连接流程,重新与数据库建立一个新的连接。

  • 使用限制

    • 会话级连接池并不能减少数据库的并发连接数。该优化只能通过降低应用与数据库的建连速率来减少MySQL主线程的开销,从而更好地处理业务请求,但是连接池里空闲的连接会短暂占您的连接数。

    • 会话级连接池也不能解决由于存在大量慢SQL,导致的连接堆积问题,此类问题的核心是先解决慢SQL问题。

事务级连接池

  • 工作原理1

    事务级连接池主要用于减少直接连接到数据库的业务连接数,以及减少短连接场景下频繁建连带来的负载。

    开启事务级连接池后,客户端与PolarDB代理间可以存在上千个连接,但代理与后端数据库间可能只存在几十或几百个连接。

    PolarDB代理本身并没有最大连接数的限制,连接数的限制主要由后端数据库中计算节点的规格决定。未开启事务级连接池时,每条由客户端发起的连接都需要在后端主节点和所有只读节点上各创建一个对应的连接。

    开启事务级连接池后,当客户端发送请求时,会先与PolarDB代理建连,代理不会马上将其与后端数据库建连,而是先从事务级连接池里查找是否存在可用的连接(判断是否为可用连接的条件:userdbname和系统变量这3个参数值是否一致)。若不存在,代理会与数据库创建一个新连接;若存在,则从连接池里直接拿出并使用,并在当前事务结束后将该连接放回事务级连接池,方便下个请求继续使用。

  • 使用限制如下:

    • 当执行以下行为时,锁定连接,直至连接结束,即该连接不会再被放到连接池里供其它用户连接使用。

      • 执行PREPARE语句

      • 创建临时表

      • 修改用户变量

      • 大报文(例如16 MB以上)

      • 使用lock table

      • 多语句

      • 存储过程调用

    • 不支持FOUND_ROWS、ROW_COUNT和LAST_INSERT_ID函数的调用,这些函数可以调用成功,但是无法保证调用结果的正确性。其中:

      • 1.13.11及以上的数据库代理版本支持在SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT *语句后直接使用SELECT FOUND_ROWS()命令。但MySQL官方已不推荐该用法,建议您将SELECT FOUND_ROWS()替换为SELECT COUNT(*) FROM tb1进行查询,详情请参见FOUND_ROWS()

      • 支持在INSERT后直接使用SELECT LAST_INSERT_ID()语句,来保证查询结果正确性。

    • 对于设置了wait_timeout的连接,wait_timeout在客户端的表现可能不会生效。因为每次请求都会从连接池中获取连接,当wait_timeout超时后,只有连接池中的后端连接会断开,而后端连接断开并不会导致客户端连接断开。

    • 除了sql_modecharacter_set_servercollation_servertime_zone这四个变量以外,如果业务依赖其他会话级别的系统变量,那么需要客户端在建连之后显式进行SET语句执行,否则连接池可能会复用系统变量已经被更改过的连接。

    • 由于连接可能会被复用,所以使用select connection_id()查询当前连接的thread id可能会变化。

    • 由于连接可能会被复用,所以show processlist或者SQL洞察中显示的IP地址和端口,可能会与客户端实际的IP地址和端口不一致。

    • 数据库代理会将所有节点上的SHOW PROCESSLIST结果合并后再返回最终结果,而在事务级连接池开启后,前端连接和后端连接的thread id无法对应。这导致执行KILL命令时可能会返回错误:ERROR 1094 (HY000): Unknown thread id:xxx。

连接池的选择

您可以根据如下建议评估选择是否开启连接池以及开启何种类型的连接池:

  • 若业务使用的多为长连接且连接数较少,或者业务本身已具备较好的连接池,那么您可以不使用PolarDB的连接池功能。

  • 若业务使用的连接数较多(如连接数需求上万)或使用的是Serverless服务(即连接数会随着业务端服务器的扩容而线性增加),且确认您的业务不涉及上述事务级连接池使用限制的场景,那么您可以选择开启事务级连接池。

  • 若业务使用的纯短连接,且业务使用场景中包含上述事务级连接池使用限制的场景,那么您可以考虑开启会话级连接池。