1. 当MySQL突然报"Too many connections"时
凌晨3点15分,监控系统突然报警,你的MySQL数据库抛出了"ERROR 1040 (HY000): Too many connections"错误。这个瞬间,所有依赖这个数据库的业务系统开始出现连接失败,用户投诉电话瞬间被打爆。作为DBA或者运维人员,此刻最需要的是快速止血,然后才是排查根因。
"Too many connections"错误意味着当前MySQL实例的所有可用连接都被占用了,新的连接请求无法建立。MySQL默认的最大连接数(max_connections)通常是151(不同版本可能略有差异),当Threads_connected达到这个值时,就会触发这个错误。
2. 30秒紧急止血方案
2.1 立即增加最大连接数(临时方案)
最快的方式是通过超级用户连接(通常需要预留一个管理员连接)执行:
SET GLOBAL max_connections = 500;这个命令会立即生效,无需重启MySQL服务。将连接数临时调大可以快速恢复业务,但要注意:
警告:这只是临时解决方案!盲目增加max_connections可能导致服务器资源耗尽,特别是内存不足时,会引发更严重的问题。
2.2 释放空闲连接
同时可以清理长时间空闲的连接:
-- 查看所有连接及其状态 SHOW PROCESSLIST; -- 终止特定连接(替换ID为实际连接ID) KILL CONNECTION [connection_id]; -- 批量终止空闲超过10分钟的连接 SELECT CONCAT('KILL ',id,';') FROM information_schema.processlist WHERE Command = 'Sleep' AND Time > 600 INTO OUTFILE '/tmp/kill_idle.sql'; SOURCE /tmp/kill_idle.sql;2.3 使用连接池管理
如果应用使用了连接池(如HikariCP、Druid等),可以临时调整连接池参数:
# HikariCP示例 spring.datasource.hikari.maximum-pool-size=50 spring.datasource.hikari.minimum-idle=103. 3分钟根因定位方法
3.1 检查当前连接状态
-- 查看当前连接数 SHOW STATUS LIKE 'Threads_connected'; -- 查看最大连接数设置 SHOW VARIABLES LIKE 'max_connections'; -- 查看连接来源分布 SELECT user, host, COUNT(*) as connections FROM information_schema.processlist GROUP BY user, host ORDER BY connections DESC;3.2 分析连接泄漏
-- 查看长时间运行的查询 SELECT * FROM information_schema.processlist WHERE TIME > 60 ORDER BY TIME DESC; -- 检查没有提交的事务 SELECT * FROM information_schema.innodb_trx WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;3.3 检查应用连接管理
常见问题包括:
- 应用获取连接后未正确关闭
- 连接池配置不合理(最大连接数过大)
- 事务未提交或回滚
- 长查询或锁等待
4. 长期解决方案
4.1 合理设置max_connections
计算建议值:
max_connections = (可用内存 - 系统预留) / 每个连接所需内存MySQL 8.0+每个线程约需要4-12MB内存(取决于配置)。例如8GB内存的服务器:
-- 永久修改(需重启生效) SET PERSIST max_connections = 300;4.2 优化连接池配置
推荐配置原则:
- 连接池最大大小不超过max_connections的70%
- 最小空闲连接根据业务波谷设置
- 添加连接验证查询
- 设置合理的超时时间
# Druid示例 spring.datasource.druid.max-active=100 spring.datasource.druid.initial-size=10 spring.datasource.druid.min-idle=10 spring.datasource.druid.max-wait=60000 spring.datasource.druid.validation-query=SELECT 1 spring.datasource.druid.test-while-idle=true4.3 实施连接监控
-- 创建监控视图 CREATE VIEW connection_monitor AS SELECT EVENT_TIME, VARIABLE_VALUE as connections FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Threads_connected';配合Prometheus + Grafana设置警报阈值(如>80% max_connections)。
5. 高级排查技巧
5.1 使用performance_schema深入分析
-- 启用连接追踪 UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_waits%'; -- 查看连接等待事件 SELECT * FROM performance_schema.events_waits_current WHERE EVENT_NAME LIKE 'wait/io/socket%';5.2 分析连接风暴模式
当出现周期性连接暴增时,可以:
- 检查应用日志对应时间点的请求
- 分析是否有定时任务未使用连接池
- 检查是否有重试机制导致雪崩
5.3 连接代理中间件
对于大规模应用,考虑使用ProxySQL或MySQL Router管理连接:
# ProxySQL配置示例 INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (10,'mysql-master',3306); INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('app_user','password',10); LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;6. 预防措施与最佳实践
- 代码审查:确保所有数据库访问都使用try-with-resources或类似机制
- 连接池监控:监控连接池活跃连接、等待线程等指标
- 定期维护:每月检查max_connections设置是否仍合适
- 故障演练:模拟连接泄漏场景测试系统恢复能力
- 架构优化:考虑读写分离减少主库连接压力
我在实际运维中总结的经验是:连接数问题往往不是数据库问题,而是应用问题。90%的"Too many connections"案例最终都能追溯到应用代码中的连接泄漏或不当管理。建立完善的连接监控和告警机制,能在问题扩大前及时发现并处理。