【MySQL运维】如何正确合理的为数据库配置连接池数量

TangLu MySQL 2023-06-07 326 0

一、正确合理的连接池计算公式

首先说结论,在为数据库进行连接池配置的时候,通常都会有一个“把连接池配置的和并发数一样大”的误区。比如某网站并发有10000左右,然后就错误的认为连接池也要配置为10000。如果系统有10000个并发,设置10000的连接池是大错特错,即便是1000都是一个庞大的数字,实际仅仅需要10来个左右的小连接池即可,让剩下的业务线程都在队列里等待。连接池数量应该等于你的数据库能够有效同时进行的查询任务数(通常不会高于2*CPU核心数)。下面是一个PostgreSQL提供的公式,基本也可以广泛地应用于大多数据库产品

连接数 = ( (CPU核心数 * 2) + 有效磁盘数 )

· 核心数不应包含超线程(hyper thread),即使打开了hyper threading也不应包含

· 如果活跃数据全部被缓存了,那么有效磁盘数将是0。随着缓存命中率的下降,有效磁盘数逐渐趋近于实际的磁盘数(对于SSD磁盘效果尚未有分析)
按照该公式,假设数据库服务器CPU是4核i7,那么数据库服务器的连接池大小应该为((4 * 2) + 1) = 9,取整为10即可。在当前连接池下跑性能测试,保证它能轻松搞定3000用户以6000TPS的速率并发执行简单查询的场景。如果连接池大小远远超过10,反而会出现响应时长增加、TPS下降的现象。这也是经常看到的一些情况,一些只有10来个并发的应用使用着一个成百上千连接池。这会对数据库造成极其不必要的负担


二、为什么连接池不需要太大

国外数据库专家针对这个问题对Oracle进行了3次压力测试:

·  数据库连接池配置为2048。开启9600个并发线程,每两次访问数据库的操作之间sleep 550ms。此时每个请求要在连接池队列里等待33ms,获得连接后执行SQL需要77ms,合计100ms

· 数据库连接池配置为1024,并发和请求方式不变。此时获取链接等待时长基本不变,但是执行SQL的耗时减少了

· 数据库连接池配置为96,并发和请求方式不变。此时队列平均等待1ms,执行SQL平均耗时2ms


为什么在没有对其他参数进行调整的情况下,只是缩小了数据库连接池就把请求响应时间从100ms左右缩短到了3ms?答案和CPU处理多任务时的上下文切换有关系。这一点也是为什么单进程的Nginx可以比多进程的Apache性能优异的原因。顺序执行A和B永远比通过时间分片“同时”执行A和B要快,这是一条计算机科学的基本法则。一旦线程的数量超过了CPU核心的数量,再增加线程数系统就只会更慢,而不是更快。

需要注意一点的是连接池的大小最终与系统特性相关。比如一个混合了长事务和短事务的系统,通常是任何连接池都难以进行调优的。最好的办法是创建两个连接池,一个服务于长事务,一个服务于短事务。再例如一个系统执行一个任务队列,只允许一定数量的任务同时执行,此时并发任务数应该去适应连接池连接数,而不是反过来。


评论