合理maxPoolSize需联动MySQL max_connections、应用实例数和SQL平均持有时长计算:先查DB硬上限与历史峰值,再按实例数均分并留余量,最后用QPS×P95耗时验证下限。

连接池大小不是拍脑袋填个 maxPoolSize=50 就完事——它必须和 MySQL 的 max_connections、应用实例数、单次 SQL 耗时三者联动计算,否则不是资源浪费就是连接雪崩。
怎么算出合理的 maxPoolSize?别套公式,直接看真实约束
真正卡住你的从来不是“我想并发多少”,而是数据库端能给你多少连接、你有多少台应用在抢、每条 SQL 拿着连接不放多久。
- 先查 MySQL 实例的硬上限:
SHOW VARIABLES LIKE 'max_connections';—— 云数据库(如阿里云 RDS)可能标称 3200,但实际按规格分配,基础版可能只有 600 - 再查历史峰值:
SHOW STATUS LIKE 'Max_used_connections';—— 如果长期维持在max_connections的 85% 以上,说明已逼近瓶颈 - 单机应用实例数要计入:比如 3 台机器跑同一服务,DB 允许 900 连接,那每台机器的
maxPoolSize建议 ≤ 250(900 × 0.6 ÷ 3 ≈ 180,再留余量) - 验证单次 SQL 持有连接时长:用慢日志或 APM 工具看 P95 执行时间,若平均 120ms,QPS=300,则理论最小需 (0.12 × 300) = 36 个连接;设
maxPoolSize=50是安全起点,不是终点
HikariCP 关键参数填错,比不配还危险
HikariCP 默认值对生产环境极不友好,几个参数填错会直接导致线程卡死、连接泄漏或频繁重连。
-
connectionTimeout必须设为 3000~5000(单位毫秒),默认 30 秒太长,接口等 30 秒才报错,用户早关页面了 -
validationTimeout必须 ≤ MySQL 的wait_timeout(单位秒),比如 DB 设了 300 秒,这里就不能填 600,否则连接被 DB 主动断开后,Hikari 还没校验就扔出Connection is closed - 禁用
testOnBorrow(Hikari 已废弃),改用connectionTestQuery=SELECT 1+idleValidationMinutes=5,空闲 5 分钟检测一次,比每次借都查轻量得多 -
leakDetectionThreshold开发环境设 10000(10 秒),能立刻暴露没 close 的Connection;生产可关,或调到 600000(10 分钟),避免误报
Druid 和 HikariCP 在连接复用上根本不是一个量级
Druid 功能多但配置复杂,HikariCP 更轻、更稳、默认行为更合理——除非你明确需要 Druid 的 SQL 监控页或防火墙功能,否则别为了“习惯”选 Druid。
- Druid 的
minIdle和maxActive名字易混淆,maxActive实际是最大总连接数,而 Hikari 的maximumPoolSize语义清晰 - Druid 默认开启
testOnBorrow,每次取连接都执行validationQuery,QPS 高时这层开销不可忽视;Hikari 默认不校验,靠后台线程保活 - Druid 的监控路径
/druid/index.html暴露在公网有风险,Hikari 依赖 JMX 或 Micrometer,天然更收敛 - 如果你用 Spring Boot 2.3+,
spring.datasource.hikari.*是自动装配的,而 Druid 需额外加 starter、配排除规则,徒增维护成本
连接池调优最常被忽略的一点:它不是静态配置
上线后不看指标,等于没调。重点盯三个数字:activeCount 是否长期 > 80% maximumPoolSize、idleCount 是否长期为 0、poolSize 是否持续接近上限。这些不是看一次就行,得结合 SHOW STATUS LIKE 'Threads_connected' 对齐——如果池里显示 45 个活跃连接,MySQL 却报告 120 个连接,说明有连接泄漏或没走连接池。


















