MySQL查询随机挂起';发送数据';地位

MySQL查询随机挂起';发送数据';地位,mysql,debugging,innodb,Mysql,Debugging,Innodb,我使用的是MySQL 5.5.25服务器,数据库使用的是InnoDB 由于mysqld进程的原因,服务器的CPU经常以100%的速度工作大约一分钟。使用ShowProcessList: Command | Time | State | Info Query | 100 | Sending data | SELECT a.prefix, a... Query | 107 | Sending data | SELECT a.prefix, a... Query |

我使用的是MySQL 5.5.25服务器,数据库使用的是InnoDB

由于mysqld进程的原因,服务器的CPU经常以100%的速度工作大约一分钟。使用ShowProcessList:

Command | Time | State        | Info
Query   |  100 | Sending data | SELECT a.prefix, a...
Query   |  107 | Sending data | SELECT a.prefix, a...
Query   |   50 | Sending data | SELECT a.prefix, a...
问题是:

SELECT a.prefix, a.test_id, a.method_id, b.test_id
FROM a
LEFT JOIN b ON b.test_id = a.test_id
AND user_id = ?
AND year = ?
所有这些列都编制了索引,因此这不是问题所在。另外,当我在phpMyAdmin中运行查询时(有足够的限制),需要0.05秒才能完成。而且,我发现自己不可能重现这个问题,这是相当令人沮丧的,即使同时执行两次这个查询,并且垃圾邮件只会给我带来40%的CPU峰值

在查询前面加上解释结果:

Id | select_type | table | type | possible_keys        | key     | key_len | ref          | rows | Extra
 1 | SIMPLE      | a     | ALL  | NULL                 | NULL    | NULL    | NULL         | 1169 | 
 1 | SIMPLE      | b     | ref  | user_id,year,test_id | test_id | 4       | db.a.test_id |   58 | 
Id | select_type | table | type | possible_keys | key     | key_len | ref          | rows | Extra
 1 | SIMPLE      | a     | ALL  | NULL          | NULL    | NULL    | NULL         |  671 | 
 1 | SIMPLE      | b     | ref  | test_id       | test_id | 4       | db.a.test_id |   49 | Using where

除非我看不到我面前的是什么,否则我正在寻找方法来发现如何调试此类问题。我已经记录了所有查询的执行时间和它们的值等。但是由于我无法重现它,我被卡住了。我应该怎么做才能弄清楚这个问题是关于什么的?

哇,多亏了马苏德·阿拉姆的评论,我发现并解决了这个问题

使用
SHOW ENGINE INNODB STATUS
对调试非常有帮助

事实证明,对于
user\u id
的某些值,数据库的处理方式不同,因此其行为不可预测,无法重现问题。通过status命令,我能够复制并粘贴当前正在运行的确切查询

这是用户id的特定值的
解释
的结果:

Id | select_type | table | type         | possible_keys        | key          | key_len | ref  | rows | Extra
 1 | SIMPLE      | a     | ALL          | NULL                 | NULL         | NULL    | NULL |  841 | 
 1 | SIMPLE      | b     | index_merge  | user_id,year,test_id | user_id,year | 4,4     | NULL |   13 | Using intersect(user_id,year); Using where
接下来的问题是如何解释这种行为。但是,要解决我的问题,只需将查询更改为:

SELECT a.prefix, a.test_id, a.method_id, b.test_id
FROM a
LEFT JOIN b ON b.test_id = a.test_id
WHERE
b.id IS NULL
OR user_id = ?
AND year = ?
其中
EXPLAIN
导致:

Id | select_type | table | type | possible_keys        | key     | key_len | ref          | rows | Extra
 1 | SIMPLE      | a     | ALL  | NULL                 | NULL    | NULL    | NULL         | 1169 | 
 1 | SIMPLE      | b     | ref  | user_id,year,test_id | test_id | 4       | db.a.test_id |   58 | 
Id | select_type | table | type | possible_keys | key     | key_len | ref          | rows | Extra
 1 | SIMPLE      | a     | ALL  | NULL          | NULL    | NULL    | NULL         |  671 | 
 1 | SIMPLE      | b     | ref  | test_id       | test_id | 4       | db.a.test_id |   49 | Using where

现在我知道了,InnoDB可以有不同的方法来执行给定不同输入值的查询。为什么?我仍然不知道。

发送数据是一个长期运行的查询的指示,无论您使用哪个引擎,因此非常糟糕

在这两种情况下,表a上都没有使用索引,幸运的是,这个表只有几百条记录。无索引或ALL(全表扫描)是需要完全避免的。记住,当您的表中有数千条甚至数百万条记录时,情况就不同了

在case中创建一个以查询为模型的索引。再次使用EXPLAIN查看引擎是否使用此索引。如果没有,您可以使用类似use INDEX(myindex)或FORCE INDEX(myindex)的提示。结果应该是惊人的

如果不是,你的指数可能没有你想象的那么好。重申整个过程


但是,请记住,如果更改查询,使用此索引可能不再合适,因此您必须再次重申。

表的行数大小是多少。禁用查询缓存(如果已启用),然后重新生成。你有什么cpu,线程数等。exucute显示引擎innodb状态\G,loog查找死锁年轻人/非年轻人,然后开始深入研究问题…感谢你的评论,如果这是一个答案而不是评论,我会接受它。