当程序弹出Connection is not available或GetConnectionTimeoutException时,表示连接池已耗尽。切勿盲目重启,按三步走:先通过数据库命令SHOW PROCESSLIST查看当前连接状态,找出执行时间最长的查询;然后对异常长事务执行KILL结束,释放资源;可临时上调连接池最大连接数以缓解压力,但需确定这只是权宜之计。
连接池满的根本原因一般有三类:约四成是连接泄漏,代码未正确释放连接;约三成五是慢SQL或长事务,连接被长时间占用;其余是配置不当,池大小过小或数据库侧限制过低。调优需从配置、代码、监控三个方面协同入手。
配置调优是确定合理的池大小。连接池并不是越大越好,过多连接会导致数据库上下文切换频繁,反而降低性能。通用公式为:连接池大小约等于CPU重要数乘以二再加上有效磁盘数。建议将最小空闲连接数和最大连接数设为相同值,使用固定池大小避免动态伸缩带来的开销。对于HikariCP,应注意三个参数:maximumPoolSize按公式设定;connectionTimeout设为三到五秒,快速失败优于无限等待;maxLifetime必须小于数据库的wait_timeout,建议设为后者的五到七成,同时开启leakDetectionThreshold来检测长时间未归还的连接。如果使用Druid,其内置的removeAbandoned功能可自动回收泄露连接并打印堆栈日志,是定位泄漏问题的利器。
数据库侧参数必须和连接池协调一致。全局最大连接数需大于等于所有应用实例连接池总和再加百分之十的预留。如果连接池的maxLifetime大于数据库的wait_timeout,将导致数据库单方面关闭连接而应用池仍认为有效,会引发连接已断开错误。
代码方面防止连接泄漏的最好是使用try-with-resources语法,任何实现了AutoCloseable接口的资源都会在语句块结束时自动释放。对于Spring事务,必须避免在@Transactional方法中执行耗时非数据库操作,如调用外部HTTP接口、发送邮件等,这些操作会长时间占用数据库连接,应移至事务外处理。
性能测试是调优效果的必要手段。通过压测工具如JMeter、Locust或Sysbench,设计梯度加压和长时间浸泡场景,观察不同配置下的吞吐量和响应时间,确定连接池大小是不是合理,并证实是不是存在慢SQL导致的连接堆积。测试过程中需监控应用层的活跃连接数、等待队列长度,数据库层的当前连接数及慢查询数量,并设定告警阈值,如活跃连接数超过最大连接的八成时触发预警。
不断监控是防止问题复发。Druid提供开箱即用的监控页面,可实时查看连接池状态和SQL执行统计;HikariCP则通过JMX暴露标准,可接入Prometheus和Grafana。建议每周巡检连接池监控面板,分析慢查询日志,核对各实例配置一致性,保证数据库连接余量充足。
连接池满的应对需按照先止损、后根治原则,通过合理的配置基线、规范的资源管理代码以及完善的监控和压测流程,将连接池从性能短板转变为系统稳定器。