bigywater.tech
Spring · 97

HikariCP 在 Boot 里的默认值,以及池耗尽时的症状

Boot 里 HikariCP 的默认值是多少?池耗尽的时候应用表现成什么?连接泄漏怎么查?池该设多大?这篇在 Spring Boot 4.0.8、HikariCP、MySQL 上逐项实测。

10 / 10
maximumPoolSize 与 minimumIdle 的默认值;启动后服务端立刻看到 10 个连接
1008 ms
池耗尽时,第 3 个请求等到 connection-timeout(1000 ms)后失败
92 → 1187
池 2 个与池 32 个连接时,32 个并发客户端的吞吐(次/秒)

默认值

实测 · 本机执行输出
  (Boot 创建的 HikariDataSource 是惰性的:第一次取连接时才真正建池;下面先 select 1 触发它)
  DataSource 的类型:com.zaxxer.hikari.HikariDataSource
  poolName=HikariPool-1,maximumPoolSize=10,minimumIdle=10,connectionTimeout=30000 ms,idleTimeout=600000 ms,maxLifetime=1800000 ms
  keepaliveTime=120000,validationTimeout=5000 ms,leakDetectionThreshold=0,autoCommit=true,connectionTestQuery=null,initializationFailTimeout=1
  启动后 1.5 秒:total=10,active=0,idle=10,waiting=0
  MySQL 服务端 show processlist 里属于本程序的连接数:10

最大 10、最小空闲 10(固定大小),连接超时 30 秒,最大寿命 30 分钟;启动后立刻建好 10 个连接。

池耗尽

实测 · 本机执行输出
  池大小 2,两个连接都被占住:total=2,active=2,idle=0
  第 3 个请求等了 1008 ms 之后失败:CannotGetJdbcConnectionException / 最里面:SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 1005ms (total=2, active=2, idle=0, waiting=0)
  两个连接放回之后再请求:1,用时 3 ms
  池大小 2、connection-timeout=3000 ms,两个连接各被占 600 ms:第 3 个请求 结果=1,等了 603 ms

等满 connection-timeout 抛 CannotGetJdbcConnectionException;没超时就是一次慢请求。

泄漏检测

实测 · 本机执行输出
  leak-detection-threshold=500:LOG WARN c.zaxxer.hikari.HikariConfig - HikariPool-1 - leakDetectionThreshold is less than 2000ms or more than maxLifetime, disabling it.
  故意不关连接,持有了 2600 ms(leak-detection-threshold=2000 ms)
  日志里和泄漏有关的行:4
    LOG WARN c.z.hikari.pool.ProxyLeakTask - Connection leak detection triggered for com.mysql.cj.jdbc.ConnectionImpl@50756c76 on thread main, stack trace follows
    java.lang.Exception: Apparent connection leak detected
  堆栈里指向我这段代码的帧:at demo.Main.main(Main.java:33)

leak-detection-threshold 不能小于 2000 ms;触发时打印持有者的堆栈。

池大小

实测 · 本机执行输出
  maximum-pool-size=2:32 个客户端线程各自循环执行 select sleep(0.02)(约 20 ms),4 秒内完成 366 次,即 92 次/秒
  maximum-pool-size=4:32 个客户端线程各自循环执行 select sleep(0.02)(约 20 ms),4 秒内完成 702 次,即 176 次/秒
  maximum-pool-size=10:32 个客户端线程各自循环执行 select sleep(0.02)(约 20 ms),4 秒内完成 1650 次,即 413 次/秒
  maximum-pool-size=32:32 个客户端线程各自循环执行 select sleep(0.02)(约 20 ms),4 秒内完成 4746 次,即 1187 次/秒

池大小决定到数据库的并发度,理想情况下吞吐随池大小线性增长。

分步演示

HikariCP
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动(HikariCP 随 spring-boot-starter-jdbc;MySQL 是本机自己起的 26.7.0 实例,mysql-connector-j)。默认值取自 HikariDataSource 的 getter(建池之后);池耗尽用两个线程占住连接;泄漏检测会让一个连接被持有超过阈值;吞吐用 32 个线程循环执行 select sleep(0.02),每种池大小跑 4 秒,单次数据
    • 没有验证:maxLifetime 与 MySQL wait_timeout 的配合以及连接被服务端断开后的行为;keepaliveTime 的实际作用(只读到默认值是 120000);idleTimeout 让池缩小的过程(housekeeper 周期较长,没有等);初始化失败(initializationFailTimeout)的行为;数据库真实负载下的最佳池大小(本篇的查询不吃 CPU);HikariCP 的 JMX 指标;多数据源下的多个池
    京ICP备2026067502号-1京公网安备11010502063487号