调大max_connections仅能临时缓解“too many connections”错误,根治需先排查连接未释放原因;快速确认是否真连满:执行show variables like 'max_connections'; show status like 'threads_connected'; show status like 'max_used_connections';若threads_connected接近max_connections才是真满,否则可能为系统文件描述符等底层限制。

直接说结论:调大 max_connections 只能临时缓解“Too many connections”错误,不是根治方案;真正要解决,得先查清哪些连接在占着不放、为什么没释放。
怎么快速确认是不是真连满了
别一看到报错就改配置。先登录 MySQL(如果还能登进去),执行这三条命令:
-
SHOW VARIABLES LIKE 'max_connections';—— 看当前上限是多少,默认是 151,很多生产环境仍没改 -
SHOW STATUS LIKE 'Threads_connected';—— 看现在实际连了多少个 -
SHOW STATUS LIKE 'Max_used_connections';—— 看历史峰值,比当前值还高,说明曾经更满过
如果 Threads_connected 接近甚至等于 max_connections,那确实是满了;但如果只有一两百连接却报错,可能是操作系统级限制(比如 ulimit -n 或 systemd 的 LimitNOFILE)卡住了,MySQL 根本拿不到足够文件描述符。
临时调参和永久生效的区别在哪
SET GLOBAL max_connections = 2000; 立刻生效,但 MySQL 重启后就回退。这适合紧急救火,比如半夜报警连不上库,先撑住业务。
永久修改必须改配置文件:
- Linux 下通常是
/etc/my.cnf或/etc/mysql/my.cnf,在[mysqld]段加一行:max_connections = 2000 - 但改完不等于就生效了——MariaDB/Percona 还可能被 systemd 限制。要检查
/usr/lib/systemd/system/mysqld.service(或mariadb.service)里有没有LimitNOFILE,它必须 ≥ 你设的max_connections值,否则 MySQL 启动时会默默按系统限制截断 - 改完配置后,必须
systemctl daemon-reload && systemctl restart mysqld,不能只 reload
为什么杀掉连接比调大参数更重要
执行 SHOW PROCESSLIST; 后,重点关注这些状态:
-
Sleep时间特别长(比如几百秒)的连接——大概率是应用没关连接,或者连接池配置不合理 -
Cleaning up卡住不动——常见于大事务提交后资源释放慢,或 buffer pool 太小导致刷脏页阻塞 -
Waiting for table metadata lock——有 DDL 正在等锁,而前面有个长事务没提交,整个链路都堵死
别手软,用这个语句生成批量 KILL 脚本:
SELECT CONCAT('KILL ', id, ';') FROM information_schema.PROCESSLIST WHERE USER = 'app_user' AND TIME > 60;
注意:不要 KILL 系统用户(如 event_scheduler、system user),也不要 KILL 正在执行 Query 的活跃会话,除非你确定它卡死了。
容易被忽略的底层瓶颈
哪怕你把 max_connections 调到 5000,如果 innodb_buffer_pool_size 还是默认的 128M,大量连接一并发查询,就会争抢 buffer pool,触发频繁刷盘和锁等待,结果所有连接都变慢、超时、重连——形成恶性循环。
同样,table_open_cache 如果太小,每个连接打开表都要反复加载、释放,CPU 和 mutex 争用会飙升,SHOW PROCESSLIST 里会出现一堆 Opening table 状态。
所以真正要调的,从来不只是一个 max_connections;它是整条链路上的水位标尺,水位高了,得看是上游漏水(应用不关连接)、管道太细(系统限制)、还是下游淤塞(buffer pool / table cache 不足)。











