先查 SHOW STATUS LIKE 'Threads_connected' 和 SHOW PROCESSLIST 确认是否真超限,重点排查未关闭的 Sleep 连接;再检查 ulimit 和连接池配置,确保应用层正确释放连接。

怎么确认当前连接数真的超了
MySQL 报错 Too many connections 时,别急着调大 max_connections。先看真实连接状态:用 SHOW STATUS LIKE 'Threads_connected'; 查当前活跃连接数;再用 SHOW PROCESSLIST; 看具体是谁占着不放——尤其是大量 Sleep 状态的连接,大概率是应用没正确关闭连接。
- 应用层未调用
connection.close()或未走连接池回收逻辑,是最常见原因 - 某些 ORM(如 Django 默认配置)在长连接场景下会复用连接但不主动释放,导致空闲连接堆积
-
wait_timeout和interactive_timeout值设得过大(比如 28800 秒),会让 Sleep 连接挂太久
查完发现 Threads_connected 接近或等于 max_connections,才说明真瓶颈在这儿。
max_connections 改多少才算合理
max_connections 不是越大越好。它直接影响 MySQL 的内存占用(每个连接约 256KB~1MB 内存开销),设太高可能触发 OOM 或拖慢响应。
- 先估算:单个应用实例平均并发连接数 × 实例数 × 1.5(留余量),比如 4 台应用各撑 100 并发,建议从
600起步 - 生产环境不建议直接设到 2000+,除非你确认 buffer pool、sort_buffer_size 等配套参数已调优
- 修改方式有两种:
SET GLOBAL max_connections = 1000;(重启失效)或改配置文件my.cnf中的max_connections = 1000后重启 mysqld
注意:动态 SET 需要有 SYSTEM_VARIABLES_ADMIN 权限,MySQL 8.0+ 才支持部分变量热改。
为什么调了 max_connections 还是连不上
改完参数仍报 Too many connections,大概率是被操作系统级限制卡住了。
- Linux 默认单进程可打开文件数限制(
ulimit -n)常为 1024,而 MySQL 每个连接至少占 1 个文件描述符 - 若
max_connections设到 2000,但 mysqld 进程的 ulimit 是 1024,实际最多只能建 1024 连接 - 解决方法:修改 systemd service 文件(如
/etc/systemd/system/mysqld.service),加LimitNOFILE=65536,然后systemctl daemon-reload && systemctl restart mysqld
顺手检查 cat /proc/$(pidof mysqld)/limits | grep "Max open files",确认生效。
连接池配置比 max_connections 更关键
数据库连接池(如 HikariCP、Druid、SQLAlchemy 的 pool_size)如果没配好,再大的 max_connections 也是白搭。
- 连接池最大值(
maximumPoolSize)应 ≤ MySQL 的max_connections,否则多个服务一起打进来就爆 - 空闲连接回收要开启:
idleTimeout(HikariCP)、minEvictableIdleTimeMillis(Druid),避免长期 Sleep 占位 - Spring Boot 用户注意:
spring.datasource.hikari.maximum-pool-size默认是 10,线上必须显式调大,不能依赖默认
一个典型错误:5 个微服务,每个池子 max=50,max_connections=200,看似够用,但高峰期叠加请求,瞬间就超。
连接数问题本质是应用与数据库之间的契约失衡。参数只是兜底,真正要盯的是连接生命周期——谁建的、谁该关、什么时候关、关没关掉。漏掉任意一环,调参就只是把报错时间往后推几天。


















