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

运维派——国内最大的IT运维社区,欢迎关注运维派微信公众号(ID: yunweipai),获取更多资讯

近期连续很长一段时间忙成狗, 没有写些文章来跟大家分享。现在接近晚上12点,但还是准备把这个bug简单分享出来。发现这个bug已有半天,现在提起来,依然心有余悸。因此将其尽早分享出来,希望各位mysql dba朋友尽量别踏入这个雷区。 到底有多严重, 请看下面的测试结果:

(这个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.

网友评论comments

发表评论

电子邮件地址不会被公开。 必填项已用*标注

  1. deeka说道:

    讲了半天,不知所云啊

  2. Lockin说道:

    测试了一下 mysql版本5.7.9 并没有发现这个问题

Copyright © 2012-2017 YUNWEIPAI.COM - 运维派 - 粤ICP备14090526号-3
扫二维码
扫二维码
返回顶部