MySQL 连接数过多导致拒绝访问的应对策略

作为长期与数据库打交道的开发者,我经常遇到MySQL连接数爆满导致应用无法访问的紧急情况。上周我们的生产环境就出现了”Too many connections”错误,整个网站陷入瘫痪状态。经过一番折腾,我总结出了一套行之有效的应对策略,今天就来分享给大家。
1. 快速诊断连接数状态
当收到连接数过多的告警时,首先要确认当前连接状态。我习惯使用以下命令查看MySQL当前的连接情况:
SHOW STATUS LIKE 'Threads_connected';
SHOW VARIABLES LIKE 'max_connections';
SHOW PROCESSLIST;
通过对比Threads_connected和max_connections的值,就能判断是否真的达到了连接上限。SHOW PROCESSLIST则能显示所有活跃连接,帮助识别异常连接。
2. 紧急情况下的临时解决方案
在业务高峰期,如果无法立即重启MySQL服务,我会先通过以下方式临时增加连接数:
SET GLOBAL max_connections = 1000;
这个命令能立即生效,但只是临时方案。重启后配置会恢复原样。记得执行后要检查系统资源是否足够支撑更多连接,否则可能导致服务器崩溃。
3. 排查并优化连接泄漏
大多数连接数过多的问题都是由于连接泄漏导致的。我通常会检查应用代码中的数据库连接是否及时关闭。比如在Java中:
// 错误示例 - 忘记关闭连接
Connection conn = dataSource.getConnection();
// 执行查询...
// 忘记调用 conn.close()
// 正确做法 - 使用try-with-resources
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
// 执行查询...
}
另外,建议设置连接超时参数,我在my.cnf中通常会配置:
[mysqld]
wait_timeout = 300
interactive_timeout = 300
4. 使用连接池优化连接管理
使用连接池是解决连接数问题的根本方法。以HikariCP为例,我常用的配置如下:
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
合理设置连接池大小很重要,不是越大越好。我一般根据应用的实际负载来调整,避免过度占用数据库资源。
5. 长期监控与预防措施
为了防止问题再次发生,我建立了完整的监控体系:
# 定时检查连接数的脚本
#!/bin/bash
connections=$(mysql -e "SHOW STATUS LIKE 'Threads_connected'" | grep Threads_connected | awk '{print $2}')
max_connections=$(mysql -e "SHOW VARIABLES LIKE 'max_connections'" | grep max_connections | awk '{print $2}')
usage_rate=$(echo "scale=2; $connections * 100 / $max_connections" | bc)
if (( $(echo "$usage_rate > 80" | bc -l) )); then
echo "警告:MySQL连接数使用率超过80%"
# 发送告警...
fi
同时,定期进行压力测试,确保系统在高并发下的稳定性。建议每月至少进行一次全链路压测。
经验总结
处理MySQL连接数问题就像医生看病,既要快速缓解症状(临时增加连接数),又要根治病因(优化代码和使用连接池)。最重要的是建立完善的监控预警机制,在问题发生前就能及时发现苗头。记住,预防永远比救火更重要!


这个错误我也经常遇到,分享很实用!