MySQL连接数飙高主因是连接未释放,需检查wait_timeout、max_connections及应用连接池配置,并排查MyISAM表锁与Aborted_connects异常。

MySQL连接数飙高,先查是不是wait_timeout和max_connections配错了
连接数持续接近或打满max_connections,八成不是业务突增,而是连接没及时释放。常见原因是应用层没正确关闭连接,或者 MySQL 自身超时设置太宽松,让空闲连接长期挂着。
关键参数要对齐:
- wait_timeout(非交互式连接)和interactive_timeout(交互式)默认都是 28800 秒(8 小时),远超大多数应用实际需要
- max_connections设得过高(比如 2000+)但没配对应内存,反而加剧内存压力
- 应用连接池的maxIdle、minIdle、maxWait必须和 MySQL 超时值配合,否则池子会不断新建连接去“填坑”
- 把
wait_timeout调到 60–300 秒,观察业务是否报MySQLNonTransientConnectionException: No operations allowed after connection closed——如果有,说明应用真在用已超时的连接,得修代码 -
max_connections别盲目堆高,按公式粗估:max_connections ≈ (可用内存 × 0.7) / 单连接平均内存占用;InnoDB 下单连接常占 2–10MB,MyISAM 更低但并发差 - 用
SHOW PROCESSLIST筛出Command = Sleep且Time远大于wait_timeout的连接,它们就是“僵尸”
InnoDB缓冲池innodb_buffer_pool_size设太大,反而拖慢连接响应
InnoDB 依赖innodb_buffer_pool_size缓存数据和索引,但它不是越大越好。设得超过物理内存 70%,会导致系统频繁 swap,新连接建立时 malloc 内存卡顿,表现就是连接耗时陡增、Threads_created飙升。
MyISAM 完全不走这个池子,它靠key_buffer_size缓存索引,数据文件直接读磁盘,所以混用引擎时容易误判瓶颈。
- 纯 InnoDB 实例:建议设为物理内存的 50%–75%,但必须留够 OS 和其他进程(如 binlog cache、sort buffer)空间
- InnoDB + MyISAM 混合:优先保
innodb_buffer_pool_size,key_buffer_size控制在 32–256MB 足够,再大无效 - 改完必须重启 MySQL;在线调整只支持 5.7+ 的
SET GLOBAL innodb_buffer_pool_size = N,但仅限于增大且需满足对齐页大小(1MB 倍数)
MyISAM 表锁引发连接堆积,concurrent_insert不是万能解药
MyISAM 是表级锁,一个INSERT或UPDATE正在执行,后面所有对该表的写操作(甚至部分读)都得排队。这时Threads_running可能不高,但Threads_connected持续上涨——连接在等锁,不是等 CPU 或 IO。
concurrent_insert设为ON(默认)只允许在表末尾追加时并发,一旦有DELETE或UPDATE导致空洞,就退化为表锁;设为ALWAYS风险更高,可能破坏REPAIR TABLE一致性。
- 查
SHOW OPEN TABLES WHERE In_use > 0,看哪些 MyISAM 表长期被锁住 - 用
SHOW PROFILE FOR QUERY N确认慢查询是否卡在Waiting for table level lock - 别指望
concurrent_insert治本,真正出路是迁移到 InnoDB,或至少把高频写的 MyISAM 表改成INSERT DELAYED(5.6 已废弃,慎用)
连接数监控不能只盯Threads_connected,Aborted_connects泄露真实问题
Threads_connected高,可能是健康流量,也可能是连接反复断开重连。这时候看Aborted_connects和Aborted_clients更准:前者是客户端连上来就挂(认证失败、包错误、超时),后者是连接建好后异常断开(网络闪断、应用没 close)。
尤其要注意Aborted_connects里含Access denied错误——说明应用配置了错密码,每秒重试几次,连接数就虚高几十个。
- 实时查:
SHOW STATUS LIKE 'Aborted%';,结合mysqladmin extended -r -i 1 | grep Aborted看变化率 -
log_warnings = 2打开后,错误日志会记录具体失败原因,比状态变量更准 - 如果
Aborted_clients持续增长,重点查应用连接池配置和网络稳定性,而不是调 MySQL 参数
真正难处理的是连接在应用层“逻辑泄漏”:比如 try-catch 里忘了 close,或用了 ThreadLocal 连接但线程复用后没清理。这种问题不会在 MySQL 状态里留下明显痕迹,得靠应用侧堆栈分析。


















