mysql CPU爆高 实战解决方案

分享mysql CPU达990%致使系统瘫痪
案发现场】半夜系统升级(正常 mysql CPU 200%左右),隔天上午8:20系统突然瘫痪(网页打开系统连接不上)以往此时系统进入正常负荷状态
服务器现象mysql CPU 990% 居高不下
汇报】给直系领导说明情况,协助解决问题
猜测】修改mysql配置文件,加大mysql运行内存
第一次尝试】查找相关问题解决方式,调大query_cache_sizetmp_table_size各增4倍
尝试结果】失败 >>> 重启mysql服务后,依然没效果
请求帮助】领导:查看mysql慢日志
定位问题】通过查看慢日志,最终系统一个统计模块查询超负荷(6个客户端每5秒实时统计一次数据
分析问题】统计涉及1个大表日志表2000w条数据(被频繁查询),主要数据表1个300w条数据,还有其他小表忽略
查看代码】多个方法里面for循环里有查询统计
临时方案】优化其中循环较大,循环里面统计较多的一个方法
第二次尝试】将for循环里面的查询提取到外层,然后分组转为map,循环里面通过关键字作为key获取后java代码进行计算(有隐患),1小时后,再次发布版本
尝试结果】有效果,但仍不理想 >>> mysql CPU占用终于降了,均值500%,可以通知客户使用了,此时才松了口气
最终方案】领导方案:1.将整个大接口所有for循环里面能提出的查询统计全提出来,用java代码计算2,做本地缓存
思考】本地缓存用什么技术,发现都不太适用,如ehcache,guava等,只能自定义缓存类了
查询的场景】由于统计的主要是日志表,不会有修改
缓存方案】用map缓存2个月前到今天0点的数据,根据特定的字段机型分组,分组后方便接口查询时可以直接get,查询的接口方面只需要统计今天的数据,然后两者数据合并;其他被查询的数据也照做
第三次尝试】编码5小时后,优化了所有的for循环里面的查询,设计并做了本地缓存,发布
尝试结果】失败 >>> 稳定观察5分钟:mysql CPU稳定在200%,但javaCPU飙升 一直维持在1700%左右,同时系统仍然无法使用
 
回滚
了解】java代码 CPU爆高的原因主要有3种:1,代码死循环;2,循环内大量创建对象导致内存泄漏;3,代码中出现密集型计算
再次优化】将代码中循环里面的计算代码,提取出来,在外层计算好,然后根据特定情况分组转为map,供循环内直接get
第四次尝试】编码2小时后,再次发布
尝试结果】 成功 >>> 现象:项目启动时候,javaCPU爆高,维持在1000%左右;1分钟后,降为30%左右,同时mysqlCPU维持在 130%左右并且6个客户端同时访问
大功告成
反省】之前经常登录服务器,一直没注意mysql和java CPU使用情况,导致这次系统崩溃来的突然,前阵有发现系统好像变得有点慢了(查询时),有想过做缓存,但没来得及做就出现了灾难。

 

 

 【注意】上次测试时,是上午的数据,所以当日统计数据量小

******************************************************************************************继上次优化后,再次优化************************************************************************************

 【注意】这次测试时,是晚上的数据,所以当日统计数据比上次统计时数据量大1-2倍

 

第一次尝试】将该模块所有能用到缓存的地方都加上本地缓存,并且尽可能少的访问数据库

失败】导致程序各种分组计算最密集,java代码CPU1000左右,居高不下

第二次尝试】将该模块明显耗性能的sql查询,抽取出来,进行选择性的加缓存优化

较符合预期】mysql CPU占用保持再100-250,均值在170左右

观察mysql CPU变化2小时

总结:性能优化一定是一步一步来,找到属于当前系统的最优方式,即java代码和mysql平衡】就像第一次尝试将所有能加缓存的地方都加上缓存,能少用一次查询就少用一次查询,这样将业务代码编写变得异常耗时,很费时间,最后结果还很不理想。

 

*************************************************************************************优化+1*********************************************************************************

优化1】查询需要的列,只返回想要的结果;

目的】减少mysql查询到的数据返回到内存的io操作

优化2】前台看板数据统计由定时刷新改为5-10秒随机刷新

目的】降低并发导致的cpu爆高的问题,(并发访问的时候,mysql CPU偶尔会到400%)

优化3】将缓存内的数据也改为需要的数据

目的】降低系统消耗的内存空间(由之前java代码内存5G-降为目前1G左右)

晒图】晚间20.30

总结】性能有提升,但不是特别明显,下一步优化则是加入增量缓存

 

*************************************************************************************优化+1*********************************************************************************

尝试】查询mysql慢日志,tail -n 10000 slow.log >> slow.log_bak ,发现有A,B两个表访问比较慢

 

 

解决】更改了其他表结构,将A表的查询替换

结果】mysql cpu使用率 效降低了,稳定再180%左右

 

再次查看慢日志】只有一个表的慢日志了

 

 

 【总结】mysql慢日志明显记录了,有问题的sql,根据慢日志去优化项目,可以明显提升项目运行效率。

 

posted @ 2020-11-17 17:47  coder-b  阅读(437)  评论(0编辑  收藏  举报