当在mysql5.7上发现这个bug,小心脏不好受了

到底有多严重, 请看下面的测试结果:


    (这个bug的线索来源一个不曾相识的朋友,前段时间通过邮件向作者请教这个问题,因为太忙,没有顾上,当时也不以为然。今天抽时间来复核这个问题,结果大吃一惊。非常感谢这个朋友)。


       一个表,表结构如下:

CREATE TABLE "user_task" (

  "id" int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',

  "parent_id" int(10) NOT NULL DEFAULT '0' COMMENT '问题id',

  "author" int(10) NOT NULL DEFAULT '0' COMMENT '发布人pid',

  "con_id" int(10) NOT NULL COMMENT '群组id',

  "type" tinyint(2) NOT NULL DEFAULT '0' COMMENT '类型(0 问题;1回答)',

  "title" varchar(200) NOT NULL DEFAULT '' COMMENT '标题',

  "info" varchar(500) NOT NULL DEFAULT '' COMMENT '文本',

  "pic" text NOT NULL COMMENT '图片(json)',

  "audio" text NOT NULL COMMENT '音频(json)',

  "start_time" int(10) NOT NULL DEFAULT '0' COMMENT '发布时间',

  "end_time" int(10) NOT NULL DEFAULT '0' COMMENT '截止时间',

  "create_at" int(10) NOT NULL,

  "modify_at" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

  "isread" tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '0 已读 1 未读',

  PRIMARY KEY ("id"),

  UNIQUE KEY "idx_con_title" ("con_id","title")

) ENGINE=InnoDB AUTO_INCREMENT=401 DEFAULT CHARSET=utf8   


这个表一个主键+一个唯一性索引。数据量也很少。

mysql> select count(*) from user_task;

+----------+

| count(*) |

+----------+

|       54 |

+----------+

1 row in set (15.76 sec)

总共54条数据。


然后我们执行下面的这些sql , 请开始仔细观察。

mysql>  SELECT distinct  con_id   FROM user_task  where id in (56,57); 

+--------+

| con_id |

+--------+

|    844 |

+--------+

mysql> explain  SELECT distinct  con_id   FROM user_task  where id in (56,57); 

+----+-------------+-----------+------------+-------+-----------------------+---------+---------+------+------+----------+------------------------------+

| id | select_type | table     | partitions | type  | possible_keys         | key     | key_len | ref  | rows | filtered | Extra                        |

+----+-------------+-----------+------------+-------+-----------------------+---------+---------+------+------+----------+------------------------------+

|  1 | SIMPLE      | user_task | NULL       | range | PRIMARY,idx_con_title | PRIMARY | 4       | NULL |    2 |   100.00 | Using where; Using temporary |

+----+-------------+-----------+------------+-------+-----------------------+---------+---------+------+------+----------+------------------------------+

查看执行计划,走了主键索引。 


mysql>  SELECT distinct  con_id   FROM user_task  where id in (56,57,58);

+--------+

| con_id |

+--------+

|    844 |

|    785 |

+--------+

2 rows in set (17.30 sec)


mysql>  SELECT distinct  con_id   FROM user_task  where id in (56,57,58,66);

+--------+

| con_id |

+--------+

|    844 |

|    785 |

+--------+


mysql>  SELECT distinct  con_id   FROM user_task  where id in (56,57,58,66,70);

+--------+

| con_id |

+--------+

|    844 |

|    785 |

+--------+

2 rows in set (20.64 sec)


mysql>  SELECT distinct  con_id   FROM user_task  where id in (56,57,58,66,70,71);


Empty set (3 min 0.16 sec)

看到了没, 妖娥子在这里出现了,where 条件范围变大了, 结果却没有了,一身汗。。。。。


   结果为什么会变没有了? 谁吃了这个结果? 查看执行计划,

mysql> explain   SELECT distinct  con_id   FROM user_task  where id in (56,57,58,66,70,71);

+----+-------------+-----------+------------+-------+-----------------------+---------------+---------+------+------+----------+---------------------------------------+

| id | select_type | table     | partitions | type  | possible_keys         | key           | key_len | ref  | rows | filtered | Extra                                 |

+----+-------------+-----------+------------+-------+-----------------------+---------------+---------+------+------+----------+---------------------------------------+

|  1 | SIMPLE      | user_task | NULL       | range | PRIMARY,idx_con_title | idx_con_title | 4       | NULL |    6 |    11.11 | Using where; Using index for group-by |

+----+-------------+-----------+------------+-------+-----------------------+---------------+---------+------+------+----------+---------------------------------------+

1 row in set, 1 warning (0.00 sec)


发现走的是idx_con_title  索引 。   


        鄙视mysql:   走这个索引也无伤大雅, 干嘛把结果弄丢了?



如果改写成group by , 如下

SELECT  con_id  ,count(*)  FROM user_task  where id in (56,57,58,66,70,71) group by con_id ; 


结果正常。


 如果将索引idx_con_title 删除, 下面sql结果正常。

 SELECT distinct  con_id   FROM user_task  where id in (56,57,58,66,70,71);


          巨坑巨坑的bug,,,,,,且在5.7.18 以及5.7.20上均出现,其他版本未测试。


       目前怀疑: 问题出现mysql的优化器上面,使用另外一个索引时,执行路径不完整(错误)导致 。明天向官方提bug.  



猜你喜欢

转载自blog.51cto.com/15057824/2648659