mysql占用CPU过高的一个解决方法

339 阅读2分钟

背景

前线同事发来一个问题, 说某系统访问巨慢,希望解决下。

排查

由于是阿里云机器,

  1. 首先去云监控里看网络流入流出,发现是正常的,没有异常网络流量波动
  2. 再去看了磁盘读写的监控,发现是有波峰情况出现的,就去该服务器看具体情况
  3. 使用top命令查看内存、CPU占用情况,发现是mysql在使用大量的内存和CPU,频繁磁盘读写,说明没用到索引,经常全表扫
  4. 去mysql里查看 show processlist; 找到状态是 Sending Data 状态的数据,然后去slow log 里查看最近的慢查询,挑出所有怀疑的SQL
  5. 拿到SQL后用 explain 去看执行计划,果然发现几个是全表扫描的

SQL优化

根据执行计划,发现该语句查询没有走到索引,就去看表的建表语句查看字段和索引:

show create table table_name \G

因为该查询语句是:

select * from table_name where account_id = 123456789 ;

非常简单的一个查询,建表语句显示已经存在 account_id 字段的索引, 但是没有走索引, 这就引出了问题了:

有索引却没走索引的几个原因:

  • 字段上使用了函数
  • 字段类型不对,触发了隐式类型转换
  • SQL优化器发现全表扫代价更低(一般是where条件复杂导致)

根据建表语句,发现 account_id 是 VARCHAR类型, 传过来的参数却是 INT 类型, 尝试加上引号

explain select * from table_name where account_id = '123456789' ;

果然正常走了索引, 查询时间也降到0.0x秒。

去代码里找对应SQL, 发现是批处理任务在使用, 改完升记后,数据库CPU果然降下来了:

image.png