mysql堵塞 sending data和sort状态多,cpu高

访问MySQL频繁超时,隔一阵子就堵塞一会儿。

用show processlist 看看正在执行的语句。表现如下:

1.有100多个语句在执行,查询语句集中在两个表A和B,大多数都是select语句,少量insert和update;

2.语句状态一半多是sending data状态,其余大多是sort 状态;

3.cpu很高;

过一会儿这些语句执行完,又恢复正常了。

刚开始怀疑表没有建索引,导致查询太慢,看一下,已经建好了索引,排除索引问题;

再看语句,sending data状态的语句是最多的,上网搜了一下,有些说是可能是query_cache太小,导致赌赛。

想了一下,应该不是这问题,在安装mysql时,四台主备mysql(正式环境主备两台,测试环境主备两台),都没有修改过这参数,其他三台是正常的,就这台不正常,应该是其他问题。

捣鼓了半天,没搞定,有点郁闷,过了一会儿,又堵了,不知道该怎么办,就把其他一条查询语句拷贝了,执行一下,结果找到问题了。

这条select语句查询结果是5万多条!那就是这张表的记录有问题。

按照账号把A表group一下,找出top20条,发现有三个账号的记录都是过万的。

再查询一下正式环境的正式mysql,执行同样的语句,发现账号记录数最多也就近千条。

认真看一下对这张表的查询语句,发现大部分都是有"order by Ftime desc limit 1"

那么就找到原因了:每次查询这三个账号中某一个时,就会查询到上万条记录,然后排序,问题就在这里了,排序太耗时,而且会导致cpu升高。

有两种方法解决:

1.删除坏数据,尽快恢复服务(治标不治本,过阵子还会出现这种数据),;

2.找到为什么会出现这种坏数据,优化查询语句,从根源上解决问题。

最终采用第2种方法,找到这种坏数据的原因,发现因为这是测试环境的mysql,这种数据的产生是不可避免的。

那就从业务的使用上解决问题,看了一下查询语句,都是只需要找到某账号在A表有没有记录,而不需要知道记录是怎么时候的,那就简单了,把"order by Ftime" 部分去掉就行,直接就是“select * from A where  xxx limit 1”。问题解决。


事后回想一下整个过程,其实走了不少弯路。

1. 从表象上看,结合第2条和第3条,sort 状态和cpu突高,应该就能判断是排序花的时间多,就应该怀疑是某些账号的记录数过多,应该先看看表的数据情况。

2. 不应该被表象迷惑,不能因为sending data 状态比sort状态多,就判断是sending data状态出问题了,一瞬间的状态,只能是作参考。

3. 四个mysql的数据是不一样的,两个备都是只写不读,不会出现查询赌赛。两个主数据库理论上是相近的,但是因为某些业务的特殊性,数据可能相差较大,这个是应该考虑到的。

4. 当找不到问题时,应该找找该表数据的来源情况、表的数据情况和数据的使用语句,也能发现一点线索。


这次问题的解决,主要是靠运气,随便拷贝一条语句,刚好是三个坏账号之一,问题找到了,运气还真是不错,哈哈,如果能头脑清醒一点,应该能更快找到问题。

你可能感兴趣的:(MYSQL)