mysql 5.7本身不引发连接风暴,但其mvcc优化与默认配置组合会加剧sleep连接堆积:readview复用延迟purge、连接池未校验有效性时连接“僵而不死”,配合wait_timeout远大于池idle超时,导致资源长期占用且更难释放。

MySQL 5.7本身不会主动引发连接风暴,但它的MVCC机制改动+默认配置组合,在读写混合高并发下容易放大连接堆积效应——不是它“制造”风暴,而是让已有泄漏或池配置问题更快暴露、更难缓解。
为什么SHOW PROCESSLIST里Sleep连接越积越多?
MySQL 5.7优化了只读事务的readview复用逻辑,但副作用是:当大量短生命周期的autocommit只读事务并发执行时,readview链表增长变慢,purge线程清理滞后,间接延长了事务相关资源(包括连接上下文)的释放时机。尤其在连接池未设validationQuery或testOnBorrow失效时,应用层以为连接还可用,实际底层线程状态已卡在Sleep但未被回收。
- 现象:
SHOW FULL PROCESSLIST中大量Command为Sleep、Time持续>60秒的连接,且Host集中在少数应用IP - 关键线索:
Threads_created值在业务低峰期仍在缓慢上升,说明连接未复用 - 注意:
wait_timeout(默认28800秒)远大于应用层连接池的idle超时,导致连接“僵而不死”
max_connections调大反而让问题更隐蔽?
盲目把max_connections从151调到1000,表面看错误少了,实则掩盖了连接泄漏和池配置失配。MySQL 5.7每个连接内存开销比5.6略高(因readview结构更复杂),500连接可能吃掉8–12GB RAM;一旦OOM触发Linux OOM Killer,进程直接被杀,比“Too many connections”更难诊断。
- 必须同步检查:
sort_buffer_size、join_buffer_size等线程级缓冲区是否随连接数线性放大 - 验证系统限制:
ulimit -n是否≥max_connections * 1.2,否则MySQL连文件描述符都不够用 - 5.7+建议开启
performance_schema,用events_statements_summary_by_digest查慢查询源头,而非只盯连接数
为什么连接池配置在5.7上更容易出问题?
MySQL 5.7默认启用innodb_read_only兼容模式和更激进的预读策略,导致某些ORM(如旧版MyBatis + Druid 1.1.10以下)在获取连接后未显式设置autocommit,事务隐式开启却未提交,连接就被长期占用。这类问题在5.6上可能因事务回滚更快而没暴露。
- 典型表现:应用日志无报错,但
INFORMATION_SCHEMA.PROCESSLIST中Command为Query、State为starting或updating,且Info字段为空或截断 - 验证方法:在应用启动后立即执行
SELECT * FROM performance_schema.threads WHERE TYPE='FOREGROUND' AND PROCESSLIST_COMMAND='Query'; - 紧急规避:
SET GLOBAL innodb_lock_wait_timeout = 10;,缩短锁等待时间,加速连接释放
真正棘手的从来不是连接数上限,而是那些Sleep状态里藏着的未关闭事务、未校验有效性、未匹配wait_timeout的连接池配置——它们在MySQL 5.7的机制下,会以更顽固的方式卡住资源。











