数据库连接池的配置看起来简单,实际上它是影响系统吞吐量和稳定性的关键环节之一。连接数设得太小,请求排队等待连接,接口响应变慢;设得太大,MySQL端的线程增多、上下文切换开销上升,反而整体性能下降。很多团队在压测时发现接口耗时飙升,排查一圈最后发现是连接池参数从来没认真调过。这篇文章以MySQL加Java技术栈为背景,详细聊聊Druid和HikariCP两个连接池的调优思路,重点讲清楚最大连接数到底应该设成多少。

一、先想清楚:最佳连接数到底怎么估算
连接池大小不是拍脑袋定的,有一个广泛使用的经验公式可以参考。对于单台MySQL实例,最佳连接数约等于核心数 乘以 2 加上 有效磁盘数。比如一台8核的服务器,没有明显磁盘瓶颈,最佳连接数大约在16到20之间。这个公式的来源是PostgreSQL官方团队的性能测试结论,核心逻辑是:数据库的活跃连接数受限于CPU和磁盘IO能力,连接数超过这个值之后,新增连接只是在排队,不会带来吞吐量提升。
需要注意的是,这个公式算出的是MySQL单实例能高效服务的总连接数,而实际生产中往往是多个应用共用一个数据库实例。所以应用侧连接池的最大连接数,应该在总连接数的基础上,按应用的请求占比和优先级来分配。比如MySQL实例按公式算出最佳值是20,有三个应用连它,那么三个应用的连接池最大连接数之和最好控制在20到30之间,而不是每个应用都设50。
另一个关键认知是:连接池不是越大越好。曾有人在MySQL上做过压测对比,把最大连接数从4逐步加到2048,TPS在连接数达到某个点后不升反降,响应时间则持续恶化。原因是活跃连接数远超CPU核数时,线程上下文切换、锁竞争的开销会吞掉大量CPU。理解了这一点,调优的方向就明确了:用尽可能少的连接满足业务吞吐需求。
二、HikariCP推荐配置与参数详解
HikariCP是Spring Boot 2.x之后的默认连接池,以高性能著称。它的配置项不多,但每个都值得仔细设置。先看一份推荐的配置示例:
spring:
datasource:
hikari:
# 最小空闲连接,官方建议与maximum-pool-size保持一致,固定池大小性能最好
minimum-idle: 10
# 最大连接数,按公式估算,一般20以内,高并发核心系统不建议超过50
maximum-pool-size: 20
# 获取连接超时时间,超过则抛SQLTransientConnectionException
connection-timeout: 3000
# 连接最长存活时间,默认30分钟,建议设为比MySQL的wait_timeout小几分钟
max-lifetime: 1740000
# 连接空闲超时,只有minimum-idle小于maximum-pool-size时才生效
idle-timeout: 600000
# 校验连接可用性的SQL,MySQL下建议用ping代替查询
connection-test-query: SELECT 1
# 借出连接前是否做活性检测,默认false,开启会有微小性能损耗
keepalive-time: 30000
这里面有几个参数要重点说明。maximum-pool-size是核心参数,建议从10起步,通过压测逐步上调,观察TPS和P99耗时的变化曲线,找到拐点即可。max-lifetime一定要比MySQL的wait_timeout小至少30秒到几分钟,否则可能出现连接在池内还活着、MySQL那边已经把它断掉的情况,应用拿到一个死连接直接报错。可以在MySQL里执行show variables like '%timeout%'确认当前值。
minimum-idle官方建议直接等于maximum-pool-size,即采用固定大小的连接池。固定池避免了连接的动态创建和销毁,稳定性更好。如果业务有明显波峰波谷且低峰期很长,可以适当调小以节省数据库资源,但要接受高峰期建连带来的抖动。另外connection-test-query在新版JDBC驱动下可以不配,因为HikariCP会优先使用驱动的isValid方法做ping,效率比执行SQL更高。
三、Druid推荐配置与参数详解
Druid是阿里开源的连接池,自带监控页面,在国内使用非常广泛。它的可配置项比HikariCP多,核心配置如下:
spring:
datasource:
druid:
# 初始化时建立的物理连接数
initial-size: 5
# 最小空闲连接数
min-idle: 5
# 最大活跃连接数
max-active: 20
# 获取连接的最大等待时间,单位毫秒,超时抛异常
max-wait: 3000
# 检测连接是否有效的SQL
validation-query: SELECT 1
# 申请连接时检测,开启会降低一点性能,但能避免拿到死连接
test-while-idle: true
# 归还连接时检测,一般关闭
test-on-return: false
# 空闲检测的时间基准,配合min-evictable-idle-time-millis使用
time-between-eviction-runs-millis: 60000
# 连接最小空闲时间,超过且保活数大于min-idle则回收
min-evictable-idle-time-millis: 300000
# 是否缓存preparedStatement,MySQL下建议开启
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
Druid调优的关键在于空闲检测这一组参数的配合。test-while-idle配合time-between-eviction-runs-millis,会在每次借出连接时判断该连接空闲时间是否超过检测周期,超过就先执行一次validation-query确认连接可用。这样既避免了test-on-borrow每次借出都校验的性能损耗,又基本杜绝了拿到断开连接的问题。回收逻辑上,连接空闲超过min-evictable-idle-time-millis且当前空闲数大于min-idle时会被关闭,防止长时间闲置占用数据库连接。
Druid的另一个优势是内置监控。开启stat过滤器后,访问/druid/index.html可以看到连接池当前的活跃数、等待线程数、SQL执行耗时分布等关键指标。调优时建议重点观察两个数据:一是WaitThreadCount,如果长期大于0,说明连接不够用,可以考虑加大max-active或排查慢SQL;二是活跃连接峰值与max-active的差距,如果峰值一直远低于最大值,说明配置过大了,可以适当调小,让资源更集中。
四、压测验证与动态调整的方法
配置调优不能只靠理论,最终要靠压测数据说话。建议的流程是:先按公式给出初始值,比如8核机器设20,然后逐步调整并发压力,记录不同连接数下的TPS、P95、P99响应时间。典型的规律是,随着连接数增加TPS先上升后趋于平缓甚至下降,而响应时间在某个点之后明显恶化,这个拐点对应的连接数就是比较合适的值。
压测之外,运行期的观察同样重要。MySQL侧可以用show processlist查看当前连接的线程状态,如果大量线程处于Waiting for table lock或执行时间很长,说明瓶颈在SQL本身而不是连接数,此时加连接只会更糟。应用侧则关注连接池的获取等待时间指标,HikariCP可通过JMX暴露acquire相关指标,Druid直接看监控页。如果等待时间长期接近connection-timeout或max-wait,就是连接不够用的明确信号。
最后补充两个实践建议。一是慢SQL优先:绝大多数连接池耗尽的场景,根因是几条慢查询长时间占用连接,优化索引和SQL往往比调大连接池有效得多。二是善用熔断降级:在依赖数据库的入口处设置并发限制,把排队挡在应用层,比让请求全部堆积在连接池等待队列里,对系统整体稳定性更有利。把这几件事结合起来,连接池调优才能真正落地。
mysql连接池调优Druid配置HikariCP最佳连接数修改时间:2026-09-12 22:56:44