连接池配置需匹配数据库负载,maxactive设为max_connections的60%~70%,启用连接有效性检测,确保事务及时释放,适配mysql 8.0+认证插件,并接入监控告警。

连接池没配对,maxActive 设再大也没用
MySQL 连接池不是“开了就加速”,关键在参数和业务负载匹配。比如 maxActive(Druid)或 maximumPoolSize(HikariCP)设得远超数据库能承受的并发连接数,结果是 MySQL 报 Too many connections,或者大量线程卡在 Waiting for table metadata lock。真实场景里,100 个连接池实例配了 20 的 maxActive,但 DBA 给 MySQL 只开了 150 的 max_connections,一压测就崩。
实操建议:
-
maxActive或maximumPoolSize建议设为数据库max_connections的 60%~70%,留出空间给后台任务、监控连接 - 务必同步调大
wait_timeout和interactive_timeout(默认 8 小时),否则连接池里的空闲连接会被 MySQL 主动断开,下次取用时抛Communications link failure - 开启连接有效性检测:HikariCP 用
connection-test-query=SELECT 1(MySQL 8.0+ 推荐isValid()),Druid 用validationQuery=SELECT 1+testOnBorrow=true(但别在高并发路径上启用testOnBorrow,改用testWhileIdle)
事务没及时释放,连接池被“悄悄吃光”
最常见却最难排查的问题:一个 HTTP 请求开启事务后,因异常未走完 commit/rollback,连接没归还池子,而是卡在 IN TRANSACTION 状态。这时 activeCount 持续上涨,新请求全卡在 getConnection 阻塞,日志里看不到报错,只看到响应延迟飙升。
实操建议:
- 所有手动管理事务的代码,必须用 try-finally 包裹,确保
connection.close()在 finally 中执行(Spring 项目优先用@Transactional,它自动处理资源释放) - 配置连接池的
removeAbandonedOnBorrow=true(Druid)或leak-detection-threshold=60000(HikariCP,单位毫秒),让池子主动回收“疑似泄露”的连接,并打日志定位源头 - 定期查 MySQL:
SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND='Sleep' AND TIME > 60,看有没有长期空闲但未关闭的连接
MySQL 8.0+ 的 caching_sha2_password 让连接池反复握手
HikariCP 或 Druid 默认用老式 mysql_native_password 握手流程,遇到 MySQL 8.0 默认的 caching_sha2_password 插件时,每次建新连接都会多一次 round-trip 认证,吞吐直接掉 20%~30%。现象是连接池 warmup 慢、首次请求延迟高,且 getConnection 耗时不稳定。
实操建议:
- 连接 URL 加参数:
&serverTimezone=UTC&allowPublicKeyRetrieval=true&useSSL=false(开发环境),生产环境必须配useSSL=true并导入 CA - 更彻底的解法:MySQL 侧把用户认证插件切回
mysql_native_password:ALTER USER 'xxx'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 确认驱动版本:必须用
mysql-connector-java:8.0.28+或mysql-connector-j:8.3.0+,旧版对新插件支持不完整
连接池监控不到位,等于没配
很多团队只配了池子,但从不看 activeCount、idleCount、poolName 这些指标,等线上慢了才去翻日志。其实 HikariCP 的 HikariDataSource.getHikariPoolMXBean()、Druid 的 DruidDataSource.getStat() 都暴露了实时状态,不接监控就浪费了最大价值。
实操建议:
- 至少暴露三个核心指标:当前活跃连接数(
getActiveConnections)、等待获取连接的线程数(getThreadsAwaitingConnection)、最近一次连接创建失败时间(Druid 的getConnectErrorCount) - 设置告警阈值:比如
getThreadsAwaitingConnection > 5持续 30 秒,说明池子真不够用了,而不是临时抖动 - 别信“连接池自动扩容”——HikariCP 不支持运行时扩缩容,Druid 的
maxActive动态改了也只影响后续新建连接,已存在的池大小不变
连接池不是开关按钮,它是数据库和应用之间的水位调节阀。参数配错、事务漏关、驱动不匹配、监控缺失,任何一个点松动,压测时都可能变成单点雪崩。真正难的不是配,是让每个连接从创建、使用到归还,全程可观察、可推断、可收敛。










