数据库连接数被打满,多半是连接开着没有关闭

来源:互联网 时间:2026-10-26

连接数报满的时候,后台第一反应是调大max_connections。这个动作能立刻止血,止完血问题还在。MySQL的默认上限是151,一个日访问几千IP的站点,正常并发远到不了这个数。真到了,说明连接开出去没还回来。也可能是某个程序一次开得太多,用完不还。判断方向错了,调大只是把爆掉的时间往后推。遇上流量高峰,还是报同样的错,只是晚来几个小时。更麻烦的是内存,连接一多,缓冲一起涨,机器先撑不住。所以这个数先别动,先看它为什么满。

先看三个数:当前打开了多少、真正在执行语句的有多少、上限又是多少。前两个在状态变量里,第三个在配置变量里。一眼就能分出是漏了还是确实不够用。

Threads_connected是已经建立的连接总数。Threads_running是此刻正在执行语句的数量。两个数差得远,说明大部分连接开着却没干活。再看SHOW PROCESSLIST,Command一列大量是Sleep。Time一列几百上千秒,这就是长连接或者干脆没关。真的并发高,应该是Threads_running跟着访问量一起涨。Sleep不该越堆越多,堆起来就是泄漏。连接数一直挂着不降,先去代码里找没关的地方,别在数据库上一遍遍调参。

有些程序用持久连接,用完不归还给系统。连接留着给下一个请求复用,省一次握手。配置里写着pconnect,或者连接池上限设得过大。几百个请求就能把额度吃掉一半。而实际在跑的语句一直不多,这就是典型的占着不用。

另一种更常见:代码在循环里new一个连接。异常分支提前return,close没执行。跑一夜,泄漏的连接越攒越多,白天一看就是满的。这类问题往往在报错之后集中爆发,跟访问量关系不大。翻代码先找循环里的连接创建。再看catch分支有没有对应的关闭动作。报错的时间点跟哪次批量任务对得上,基本就锁定了。

临时处理可以SET GLOBAL max_connections,立刻生效。重启就丢,只适合应急。长期改就落到配置文件,加在mysqld段下面。改完重启服务才生效,顺序别弄反。改完查一遍@@max_connections,别只看配置文件。

连接数不是越大越好。每个连接都要占线程栈和排序缓冲。加到一千,内存先顶不住。表现会从连接报错换成进程被系统杀掉,问题反而更难查。

改完记一次基线,把连接数、访问量、内存占用一起记下来。下次再报满,对着这三个数字看。三个一起涨是访问变了,只有连接数涨是漏了。基线比任何一次调参都值钱。

相关文章

标签:

A5创业网 版权所有

返回顶部