技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

子干
• 阅读 909
作者:Agate Li
爱可生研发团队成员,负责数据库管理平台相关项目,.Net 技术爱好者,长期潜水于技术圈。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

背景

MySQL 中的 RAND() 函数是一个随机数发生器,可以返回一个 >=0<1.0 的随机浮点数。

最近在实际使用过程里遇见了一个主流版本中非常诡异的 Bug,故整理出来,以免大家踩坑。

演示

文中使用的 MySQL 版本是 5.7.25,话不多说,直接上演示:

1、创建测试表

CREATE TABLE test (`id` INT(3) NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE=`InnoDB`;

2、往表里插入 10 条记录

INSERT INTO test VALUES(),(),(),(),(),(),(),(),(),(); 

3、关键来了,执行几次下面这条 SQL

SELECT sub.rnd FROM (SELECT FLOOR(RAND()*10) rnd FROM test) sub WHERE sub.rnd<3;

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

明明指定了筛选内层 sub.rnd 小于 3 的条件,输出出来的结果却完全不对。

4、接下来排查问题的触发条件

由于直接使用 RAND() 函数输出出来的结果是随机的,首先要做的就是指定一枚固定的种子,一是以免干扰后续排查,二是可以让大家自行精确复现。

首先将种子设定为 100,并多次查询内层的随机数

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

可以看到,符合预期。继续:

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

仍然符合预期,看起来不像是 RAND() 函数本身的问题。

5、为第三步中的 SQL 指定种子:

SELECT sub.rnd FROM (SELECT FLOOR(RAND(100)*10) rnd FROM test) sub WHERE sub.rnd<3;

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

熟悉的味道出现了,刺激的感觉回来了…… EXPLAIN 一波

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

6、去掉第三步中的 test 表再试

SELECT sub.rnd FROM (SELECT FLOOR(RAND(100)*10) rnd) sub WHERE sub.rnd<3;

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

哈?并没有问题?再 EXPLAIN 一波

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

到这里就有了个怀疑,是不是跟派生表物化相关?

7、再改改第三步中的 SQL

SELECT sub.rnd FROM (SELECT FLOOR(RAND(100)*10) rnd FROM test LIMIT 10000) sub WHERE sub.rnd<3;

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

再再 EXPLAIN 一波

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

嗯,不出所料呢。这回结果对了。

8、再验证一次,把第三步中的 SQL 拉平

SELECT FLOOR(RAND(100)*10) rnd FROM test HAVING rnd<3;

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

再再再 EXPLAIN 一波

技术分享 | 使用 RAND() 函数过程中发现的诡异 Bug 分析

没错,还是熟悉的味道,还是刺激的感觉。

9、这时候可以推测,大概率是在派生表未物化的情况下 RAND() 在外层重算了……

拿着推测,去 google 一波,立刻找到了一个相关 Bug:
https://bugs.mysql.com/bug.ph...

嗯,2017 年年中就有人报过的 Bug,再看看 Bug 状态,噢,“嘻嘻,我们验证了但不打算修”……

好在官方还是给出了解决方法:

  • 对于5.7,跟我们的做法一样,加上 LIMIT <一个很大的数>;
  • 对于8.0,加上 no_merge。

文末例行完结撒花。

点赞
收藏
评论区
推荐文章
Stella981 Stella981
3年前
React Hooks实现异步请求实例—useReducer、useContext和useEffect代替Redux方案
<blockquote本文是学习了2018年新鲜出炉的ReactHooks提案之后,针对<strong异步请求数据</strong写的一个案例。注意,本文假设了:<br1.你已经初步了解<codehooks</code的含义了,如果不了解还请移步<ahref"https://reactjs.org/docs/hooksintro.html
Stella981 Stella981
3年前
Navicat for MySQL 查看BLOB字段内容
转:NavicatforMySQL查看BLOB字段内容版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/L905128009/article/details/75938472Navicatfor MySQL(https://www
Wesley13 Wesley13
3年前
Oracle 19c 之 RPM 包安装初体验 CDB(二)
!(https://oscimg.oschina.net/oscnet/594c4473f1ac3c736d43ffeaf778a1ee189.gif)作者|JiekeXu来源| JiekeXu之路(ID:JiekeXu\_IT)转载请联系授权| (微信ID:xxq1426321293)大家好,我是JiekeXu,
Stella981 Stella981
3年前
OpenCV开发笔记(七十):红胖子带你傻瓜式编译VS2017x64版本的openCV4
若该文为原创文章,未经允许不得转载,经允许后转载请注明原文地址本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107837715(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fqq214
Stella981 Stella981
3年前
HTML5新增input标签属性
一.inputtype属性1<formaction""2邮箱<inputtype"email"name""id""<inputtype"submit"value"提交"<br/<br/3手机号码<inputtype"tel"name
Wesley13 Wesley13
3年前
MySQL开源工具推荐,有了它我卸了珍藏多年Nactive!
!(https://oscimg.oschina.net/oscnet/6d37ed1e91ea4607a92fd8fda95dab9f.jpg)作者|王磊来源|Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG\_Stone)最近无意间发现了一款开源免费的MySQL客户端管理工具,磊哥
Stella981 Stella981
3年前
API测试工具SoapUI & Postman对比分析
本文由葡萄城技术团队于开源中国原创并首发转载请注明出处:葡萄城官网(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.grapecity.com.cn%2F),葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。最近公司要引入API测试工具,经过调查和
Wesley13 Wesley13
3年前
Java中的5大队列,你知道几个?
!(https://oscimg.oschina.net/oscnet/413dba940d7047ee828abcda51d24e4a.jpg)作者|王磊来源|Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG\_Stone)本文已收录至https://github.com/vipstone
Wesley13 Wesley13
3年前
Oracle 11g SYSAUX 和 SYSTEM 表空间回收相关知识点
!(https://oscimg.oschina.net/oscnet/7154fd6b2058481695445a2a9697b616.gif)作者|JiekeXu来源| JiekeXu之路(ID:JiekeXu\_IT)转载请联系授权| (微信ID:xxq1426321293)大家好,我是JiekeXu
Stella981 Stella981
3年前
DevOps 10大IT管理工具
本文为普元软件产品部总经理王葱权原创翻译DevOps技术文章系列,独家授权EAII企业架构创新研究院(微信号:eaworld)发布,转载请注明出处,违者必究。写在前面(译者自序)很久没有写博客了,几乎不知道如何开始。多年过去,已经没有转载的热情,想想该干点啥呢?我们数字化企业云平台团队近期在研发DevO
Stella981 Stella981
3年前
C++笔记002:VS2010报错:LINK fatal error LNK1123 转换到 COFF 期间失败文件无效或损坏
 原创笔记,转载请注明出处!点击【关注】,关注也是一种美德~错误描述:1已启动生成:项目:FirstCode,配置:DebugWin321生成启动时间为2018/2/521:00:30。1InitializeBuildStatus:1 正在