HikariCP 连接池参数与常见调优
每次访问数据库都新建连接开销巨大,连接池复用连接是标配。HikariCP 是 Boot 默认连接池(引入 spring-boot-starter-jdbc/data-jpa 即默认使用),以快著称。调优的核心不是把参数调大,而是理解每个参数的语义再对症下药。
默认参数
| 参数 | 默认值 | 含义 |
|---|---|---|
| maximumPoolSize | 10 | 池中最大连接数 |
| minimumIdle | 同 maximum | 最少保持的空闲连接 |
| connectionTimeout | 30000 ms | 借不到连接的最长等待 |
| idleTimeout | 600000 ms | 空闲连接回收(仅当 minimumIdle < maximum 时生效) |
| maxLifetime | 1800000 ms | 连接最大寿命(30 分钟) |
| leakDetectionThreshold | 0(关闭) | 连接借出超时告警阈值 |
| autoCommit | true | 借出连接是否自动提交 |
配置写法
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: '******'
hikari:
pool-name: DemoPool
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
max-lifetime: 1200000 # 20 分钟,需小于数据库空闲超时
idle-timeout: 600000
leak-detection-threshold: 60000 # 借出超过 60 秒未归还则告警
配置键统一 kebab-case(maximum-pool-size),只有默认值够用时可以完全不写 hikari 段。
常见调优场景
- 池大小不是越大越好:经验起点按 CPU 核数与 IO 等待比例估(常见 10~50),再用压测找拐点。池过大时,请求大量堆积在数据库端排队,RT 反而上升;
- 连接获取超时(connectionTimeout):抛 SQLTransientConnectionException 说明池被借空。先查慢 SQL 和长事务占着连接不放,而不是一味加大池子;
- 连接被服务端掐断:MySQL 默认 wait_timeout 约 8 小时,空闲连接会被数据库关闭,客户端不知情继续用就报"Connection is not available/communications link failure"。解法是
max-lifetime明显小于数据库空闲超时(如 20~60 分钟),让池在服务端回收前主动换新连接; - 连接泄漏定位:事务开了没提交/忘记归还连接时,活跃连接只增不减。把
leak-detection-threshold设为比单请求最长耗时略大(如 60s),HikariCP 会打印泄漏告警栈; - 慢启动预热:服务刚启动时连接是懒创建的,高并发突增会瞬间借空池。可用启动预热(如健康检查前执行几次轻查询)或按需调大 minimumIdle;
- 观察指标:配合 Actuator/Micrometer(第 40 章)看
hikaricp_connections_active、hikaricp_connections_pending(排队借连接的线程数)与hikaricp_connections_timeout,pending/timeout 增长是池不够或连接被占的信号(指标注册细节以官方文档为准)。
几个易混淆点
idleTimeout只在 minimumIdle 小于 maximumPoolSize 时有意义,池永远最小保持 minimumIdle 条;maxLifetime是连接寿命上限,不是空闲时间——即便连接一直被使用,到期也会被温和替换;- 事务超时(@Transactional timeout)是业务层概念,与 connectionTimeout(借连接超时)不是一回事;
- MySQL 8 驱动基于 JDBC4 的 isValid 自动做连接活性校验,一般无需再配 validation-query。
小结:HikariCP 默认值已适合多数场景;调优从"连接从哪流失"入手——慢 SQL/长事务查 active,空闲被掐查 maxLifetime,泄漏查 leak-detection-threshold,再配合池指标做决策。