当前位置:首页 >  IDC >  服务器 >  正文

MySQL 1040 Too many connections:连接泄漏定位与上限设定

 2026-09-04 14:27  来源: 互联网   我来投稿 撤稿纠错

  一键部署OpenClaw

网站隔三差五报一句数据库连接失败,刷新两下又好了。这种时好时坏的毛病最烦人,因为它不像宕机那样干脆,你没法守在屏幕前等它出现。等到真去查的时候,现场早没了。

MySQL 从 5.7 起 max_connections 默认就是 151,8.0 也沿用了这个值。超过之后新连接直接被拒,报 ERROR 1040。看到这个错,第一反应通常是把上限调大。我劝你先别急,因为多数情况下这不是容量问题,是连接泄漏。

怎么区分?看三条状态。Max_used_connections 是启动以来的峰值,如果它离上限还差得远就报了 1040,说明是瞬时尖峰;Threads_connected 是当前连接数;Connection_errors_max_connections 是被拒绝过的次数,这个数字只要不是 0,就说明上限确实被碰到了。

真正能定性的是 processlist 里的状态分布。如果大部分连接都挂在 Sleep 上,那就是泄漏——程序拿了连接不还,连接闲着占内存,还把名额占满了。这种情况你把上限调到 1000 也没用,只是把崩的时间往后推,等内存吃干抹净,OOM 就来了。

每个连接都要吃掉一块内存,来自 sort_buffer、join_buffer、read_buffer、read_rnd_buffer、thread_stack 这几个按连接分配的缓冲区。按默认配置算,一个连接大约 2 到 4 MB。把上限从 151 提到 1000,光连接本身就要多备两三个 G,这笔账得先算清楚。

-- 连接数体检:先看状态,再决定要不要调上限

 

-- 1. 上限、峰值、当前值、被拒次数,四条一起看

SHOW VARIABLES LIKE 'max_connections';

SHOW STATUS LIKE 'Max_used_connections';

SHOW STATUS LIKE 'Threads_connected';

SHOW STATUS LIKE 'Connection_errors_max_connections';

 

-- 2. 连接都在干什么:Sleep 多就是泄漏,Query 多才是真忙

SELECT command, count(*) AS cnt,

       max(time) AS max_time_sec

FROM information_schema.processlist

GROUP BY command ORDER BY cnt DESC;

 

-- 3. Sleep 超过 60 秒的连接,是重点怀疑对象

SELECT id, user, host, db, time, state

FROM information_schema.processlist

WHERE command = 'Sleep' AND time > 60

ORDER BY time DESC LIMIT 20;

 

-- 4. 单个连接的理论内存开销(MB)

SELECT ROUND((

  @@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size

  + @@join_buffer_size + @@binlog_cache_size + @@thread_stack

) / 1024 / 1024, 2) AS per_connection_mb;

 

确认是泄漏之后,处置方向就明确了:让空闲连接早点释放。wait_timeout 管非交互连接、interactive_timeout 管交互连接,默认都是 28800 秒也就是 8 小时,对 Web 应用来说长得离谱。改成 300 秒,空闲五分钟的连接自动断开,名额就回来了。

但这是治标。真正的病根在程序里——查询完没关连接、异常分支漏了释放、异步任务里拿了连接没还。改 wait_timeout 只是让泄漏的速度赶不上回收的速度,程序该修还得修。顺便说一句,长连接不是不能用,但要配合连接池,让池来控制总量,而不是让每个请求自己去连。

真到了业务确实需要更多连接的那天,再按内存算上限:可用内存减去 InnoDB 缓冲池、减去系统开销,剩下的除以单连接内存。算出来多少就是多少,别填整数也别往上凑。改完记得同步检查操作系统的文件描述符限制,那个数不够的话 MySQL 起不来。

数据来源:MySQL 8.0 官方参考手册

申请创业报道,分享创业好点子。点击此处,共同探讨创业新机遇!

相关标签
网站服务器
mysql

相关文章

  • PHP-FPM 进程耗尽:pm.max_children 用内存反推怎么算

    间歇性502里最磨人的一种:低峰期一切正常,流量一上来就崩,过会儿又自己好了。FPM日志里翻出serverreachedpm.max_children,基本就能确诊——子进程开到上限,新请求没进程可用了。很多教程看到这条日志就让你把pm.max_children调大,却不说调到多少。拍脑袋填个100

  • PHP 500 错误定位四步:日志、开关、堆栈、复现

    500和502的差别,一句话说清:502是Nginx拿不到上游响应,500是PHP自己跑着跑着崩了,然后把这个错误码一路传回浏览器。所以500的现场一定在PHP侧,去Nginx的error.log里翻是找不到的。第一步,确认错误到底出在哪一层。curl拿状态码只是看到表象,真正的判断依据是响应头里有

  • Nginx 504 Gateway Timeout:超时链路上每一环怎么查

    504和502经常被混为一谈,但两者的含义差得远。502是Nginx压根联系不上上游,504是联系上了、请求也发过去了,可上游迟迟不回话,Nginx等不下去了。换句话说,502是后厨关门了,504是后厨开门营业,只是做菜太慢。这个区别决定了排查方向完全不同。502查的是上游在不在,504查的是上游为

    标签:
    网站服务器
  • Nginx 502 Bad Gateway:从 PHP-FPM 到上游的四段排查

    502的全称是BadGateway,翻译过来叫坏网关。这个翻译其实挺误导人的,因为它让人以为网关坏了。真实情况是:Nginx好端端地在那儿,问题永远出在它背后的上游服务,绝大多数时候就是PHP-FPM。搞清这一点,排查方向就不会跑偏。第一段,确认FPM还活着。systemctlstatusphp-f

  • 服务器故障排查总纲:按现象反查的五层定位法

    网站挂了的那一刻,绝大多数人的第一反应是重启。重启Nginx、重启PHP、实在不行重启服务器。这套动作有一半概率管用,但管用的那一次你也不知道为什么管用。下次它还会来,而且大概率挑你最忙的时候来。我后来给自己定了条规矩:不管什么故障,都按固定的五层顺序往下查,每层只用一两条命令确认是或不是,绝不跳层

热门排行

信息推荐