Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.3k views
in Technique[技术] by (71.8m points)

mysql5.7遇到个奇怪的问题

数据库用的5.7.18,500多万条数据,uid有索引,出现个奇怪的问题:
如果ASC后 limit 4条没有问题
image

但是同样的语句如果 limit 1到3条,直接卡死
image

EXPLAIN这条语句又正常:
image
image

多次测试DESC没有此问题,只有使用了ASC且limit 1-3 范围内才会出现直接卡死情况,请问这种问题应该往哪个方向排查?
是否是mysql这个版本的bug这种可能性?
(后期多次测试发现是 limit=1 且和 ORDER BY组合的情况下才会出现随机选择索引,和DESC无关)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

找到原因了,这就是mysql5.7的一个坑:
搭建了 5.7.24 和 5.7.18 多次还原测试,当 limit 等于1,uid 和 order by 的字段create_time 都存在索引,那么mysql就会随机性在 uid 和 create_time 选择一个索引查询,如果选择了 create_time 他就按照order by 排序全表扫,直到查到最近对应的uid一条数据,这样就变的很卡,不知道为什么第一次查他基本选择uid查,所以测试不会出现问题,但是后面多次查他又抛弃了uid使用了create_time扫。

测试:

CREATE TABLE `testsql` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `uid` int(10) unsigned NOT NULL COMMENT 'UID',
  `pull_qr` varchar(50) NOT NULL COMMENT '任意数据',
  `type` tinyint(1) DEFAULT NULL COMMENT '任意数据',
  `check_status` tinyint(1) DEFAULT '0' COMMENT '状态:0未完成,1已完成',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `uid` (`uid`),
  KEY `create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='测试数据';

把这个表随机写入500万条数据,对应uid数据不会超过1万条,然后查询:

SELECT `id`,`pull_qr` FROM `testsql` WHERE `uid` = '1' AND `check_status` = 0 AND `type` = 1 ORDER BY `create_time` ASC LIMIT 1

第一次查基本会以UID为索引查,没问题,后面断开,再查,多次重复操作,他居然只走 create_time 索引扫了,总结就是当 possible_keys 为uid key 为 create_time 的时候,有一定概率会使用 create_time 排序后扫下来,直到扫到对应的一条uid才停止。

最终解决方案:force index(uid) 强制走指定索引

相关类似文章:
https://developer.aliyun.com/article/51065


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...