调大max_connections只是掩盖问题,根因在于连接生命周期管理不当,如应用未释放连接、连接池配置错误或长事务阻塞,易引发内存压力与锁竞争。
Too many connections 不是配置调大就完事?MySQL 报 Too many connections,表面看是 max_connections 设低了,但真实根因往往藏在连接生命周期管理里。数据库连接不是“用完即关”的资源,一旦应用端没正确释放(比如没调用 connection.close()、连接池配置失当、长事务阻塞),连接就会堆积并最终耗尽。单纯调高 max_connections 只是掩盖问题,还可能加剧内存压力和锁竞争。
SHOW PROCESSLIST 要看什么执行 SHOW PROCESSLIST 或更全的 SELECT * FROM information_schema.PROCESSLIST,重点盯三列:
State 是 Sleep 但 Time 超过 60 秒 → 很可能是应用拿了连接没归还,或连接池 idle timeout 没生效Command 是 Query 且 Time 持续增长 → 正在跑慢 SQL,可能卡住整个连接User 和 Host 集中在某几个应用 IP → 定位到具体服务,而不是所有连接都均匀分布注意:root 用户的连接也得看——运维脚本或监控工具如果没设连接超时,也可能悄悄吃掉配额。
Java 应用常见用 HikariCP,Python 常用 SQLAlchemy + Pools,它们的默认值往往不适合生产:
maximumPoolSize 别盲目设成 100+;应按接口 QPS × 平均响应时间(秒)× 安全系数(1.5~2)估算,再结合 DB 的 max_connections 反推上限connection-timeout(如 30000)和 idle-timeout(如 600000),否则空闲连接永远不释放leak-detection-threshold(如 60000),能捕获忘记 close() 的代码路径pool_recycle 建议设为 3600,避免 MySQL 的 wait_timeout(默认 28800)提前断连引发异常靠单次 SHOW PROCESSLIST 不够,要连续观察趋势:
SELECT VARIABLE_VALUE FR
OM performance_schema.global_status WHERE VARIABLE_NAME = 'Threads_connected'; 每 10 秒采一次,画折线图——如果是缓慢爬升后卡在高位,基本是泄漏;如果是尖峰冲顶后回落,才是流量问题Connection borrow timeout 或 Cannot get JDBC connection 类错误,定位到具体方法栈
Aborted connection,这常意味着客户端异常断连,而服务端连接未及时清理真正难排查的是“半泄漏”:连接被归还给池,但池认为它还可用,其实底层 socket 已失效,下次取出时才报错——这种得靠连接测试语句(如 SELECT 1)+ test-on-borrow 配合抓包验证。