连接池结合MySQL配置要点
做Web开发时,数据库响应慢是个常见问题。尤其在高并发场景下,每次请求都新建MySQL连接,不仅耗资源,还容易拖垮服务。这时候,连接池就派上用场了。合理配置连接池,再搭配MySQL的优化参数,系统稳定性能提升一大截。
连接池不是越大越好
很多人觉得连接池设得大,就能扛住更多请求。其实不然。比如你服务器MySQL最大连接数是150,应用部署了3台实例,每台连接池设成100,那理论上最多可能产生300个连接,直接超限。结果就是大量请求卡在等待连接,数据库也跟着崩。
建议连接池大小控制在MySQL max_connections 的70%以内,留出空间给后台任务或其他服务。一般项目中,单实例20~50个连接已经够用。
关键参数:空闲连接与超时时间
连接池里不能光放着一堆长期不用的连接。MySQL默认wait_timeout是8小时,超过这个时间没操作的连接会被自动断开。如果连接池不检测,拿着一个已经被MySQL关掉的连接去执行查询,就会报错。
所以要在连接池配置中开启空闲检测:
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<property name="minEvictableIdleTimeMillis" value="300000" />这段配置的意思是:每隔60秒检查一次空闲连接,超过5分钟没用的连接就干掉,同时确保检查时连接是可用的。
MySQL这边也得配合
光改应用没用,数据库本身也得调。查看当前设置:
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'wait_timeout';如果max_connections还是默认的150,业务量大时肯定不够。可以改成300或更高,但要注意内存消耗。每个连接大概占用256KB到1MB内存,算清楚再调。
wait_timeout可以适当缩短,比如设成300秒(5分钟),避免僵尸连接占资源:
SET GLOBAL wait_timeout = 300;记得写进MySQL配置文件,否则重启就失效了。
连接泄漏比高并发更危险
开发时常见问题是忘了关连接。比如一段代码查完数据库没及时释放,连接一直被占着。时间一长,连接池被打满,新请求全卡住。
解决方案很简单:用try-with-resources或者finally块确保连接关闭。Java里常见写法:
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
// 执行查询
} catch (SQLException e) {
// 处理异常
}
这样哪怕出错,连接也会自动归还池中。
监控和日志别忽略
上线后要盯着连接池的使用情况。比如当前活跃连接数、等待获取连接的线程数。很多连接池如HikariCP自带指标输出,可以接入Prometheus做可视化。
如果发现“等待连接”的线程突然增多,说明池子小了或者有慢查询占着连接。这时候查MySQL的SHOW PROCESSLIST,看看有没有卡住的SQL。
实际运维中,有个电商项目在大促时突然接口变慢。查下来发现不是数据库扛不住,而是连接池里30个连接全被几个慢查询占着,其他请求只能排队。优化SQL后,响应立马恢复正常。