MySQL查询随机挂起"发送数据"状态?

Yet*_*eti 8 mysql debugging innodb

我正在使用MySQL 5.5.25服务器和InnoDB用于我的数据库.

由于mysqld进程大约一分钟,服务器的CPU通常工作在100%.使用SHOW PROCESSLIST:

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...
Run Code Online (Sandbox Code Playgroud)

有问题的查询是:

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 = ?
Run Code Online (Sandbox Code Playgroud)

所有这些列都是INDEXED,因此这不是问题.此外,当我在phpMyAdmin中运行查询(具有足够的LIMIT)时,完成需要0.05秒.另外,我发现自己无法重现这个问题是非常令人沮丧的,即使同时执行此查询两次并且发送垃圾邮件只会给我40%的CPU峰值.

使用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 | 
Run Code Online (Sandbox Code Playgroud)

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

Yet*_*eti 8

哇,感谢Masood Alam的评论,我发现并解决了这个问题.

使用SHOW ENGINE INNODB STATUS结果非常有助于调试.

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

这是该EXPLAIN特定值的结果user_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
Run Code Online (Sandbox Code Playgroud)

现在的后续问题是如何解释这种行为.但是,为我解决问题只是将查询更改为:

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 = ?
Run Code Online (Sandbox Code Playgroud)

其中的EXPLAIN结果是:

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
Run Code Online (Sandbox Code Playgroud)

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