mysqli::real_connect(): (08004/1040): Too many connections,MySql操作缓慢:copying to tmp table

背景

生产环境MySQL数据库突然打开了很多链接Too many connections,导致整个网站瘫痪了2个小时,网站无法访问,重启数据库重启服务器都无济于事,由于我们项目相对来说比较庞大,经过无数人的打磨,所以给排查带来了一定的困难,于是得空总结了下这两个小时的漫长的时间的排查解决思路和方法。

MySQL error log

mysqli::real_connect(): (08004/1040): Too many connections,MySql操作缓慢:copying to tmp table_第1张图片

头次遇到这样的问题,难免感觉束手无策,大致有如下排查方向:

看线上进程,看运行SQL,看运行最久的,看SQL状态。

问题排查

方向1:有人建议:max_connections  这个值可以先改大一点临时解决一下问题先  。其实这里是严重的bug,估计改大也没多大意义,主要还是要找到问题的进程SQL。

方向2:执行 show processlist命令

注解:show processlist 是显示用户正在运行的线程,需要注意的是,除了 root 用户能看到所有正在运行的线程外,其他用户都只能看到自己正在运行的线程,看不到其它用户正在运行的线程。除非单独个这个用户赋予了PROCESS 权限。

方向3:执行show variables like ‘%timeout%’命令

查看超时,或锁死情况。得出结论:使用数很大,但是没有锁 。

mysqli::real_connect(): (08004/1040): Too many connections,MySql操作缓慢:copying to tmp table_第2张图片

方向4:执行show engine innodb status命令

那show engine innodb status 展示了多少信息,这些信息对系统的状态,如果不知道怎么看看看 这篇博文

发现有个sql 一直在 copy tmp table,connect数一直在增,buffer缓冲池已经占用完了。

mysqli::real_connect(): (08004/1040): Too many connections,MySql操作缓慢:copying to tmp table_第3张图片

再次执行 show processlist 查看当前的SQL进程,专门认真分析了下

最后发现真正的罪魁祸首,这条SQL一直在执行,并copying to tmp table 复制到临时表中,找到这条SQL也就知道是什么业务了,原来是 "异常通知的服务" 定时任务,后面临时停了这个业务,网站得以恢复访问,接着专门对该业务做紧急优化。

mysqli::real_connect(): (08004/1040): Too many connections,MySql操作缓慢:copying to tmp table_第4张图片

 

最后总结

是由于前一天上线版本中,有人给表加字段加索引导致的,第一天由于是晚上系统空闲期,没有发现该问题,第二天工作人员用该系统就一直打不开了。 

关键步骤:
主要执行 show processlist,看到所有操作表的线程 
发现 state状态为copy to tmp table,这是因为临时结果集大于tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存

解决方案:

暂时停掉该SQL的业务,紧急优化sql。更多MySQL优化方法请看这篇博文:https://blog.csdn.net/u012104435/article/details/50915604

反思:

上面贴出来的排查方向,是主要正确方向,也有很多错误方向和无关重要的方向就没有贴出来了,排查过程异常紧张和曲折,希望下次遇到类似的问题能迎刃而解了。

 

你可能感兴趣的:(MySQL)