zoukankan      html  css  js  c++  java
  • 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,根据慢日志去优化项目,可以明显提升项目运行效率。

  • 相关阅读:
    IP掩码的作用
    linux shell 笔记
    ubuntu apt-get Failed to fetch Temporary failure resolving 'security.ubuntu.com'
    ubuntu 16.04 & 18.04 远程桌面使用
    取消Ubuntu开机硬盘自检
    linux shell 脚本输入参数解析
    Ubuntu 16.04 + python3 源码 安装+使用labelImg最新版
    用tinyxml2读写xml文件_C++实现
    常用工具问题及解决方案
    可视化调试工具
  • 原文地址:https://www.cnblogs.com/cyrbjh/p/13995403.html
Copyright © 2011-2022 走看看