在使用mysql的过程中,发现了一个神奇的bug。
mysql语句如下:
select random_val from (select floor(rand()*10) as random_val from Test) b where b.random_val <3;
其中,Test表是个无关轻重的表(毕竟并没有从里面取数据,只是得到的结果跟Test内的数据条数有关),我也展示一下它的内容吧,其实无关紧要。
下面展示sql语句执行的奇怪之处了:
我在where中限制了random_val<3, 但是结果中仍然出现了random_val>=3的内容。
经验证发现,这个问题是否出现,与mysql的版本有关。版本5.6.21及以下,不会出现这个问题,而版本5.7.11以上,包括最新的8.0.11版本,都会出现这个问题。
考虑到有可能是mysql的一个bug,我去官网上查issue。发现已经有人提bug单了。https://bugs.mysql.com/bug.php?id=86624
那个人也发现,当子查询中有rand()时,每次引用到rand()都会重算一次,如下图。
但是这个bug单,官方似乎不以为意,已经一年多没人回复了。只是MySQL的高级首席工程师Roy Lyseng在结尾提出了权衡的解决方案:对于5.7的版本,在子查询中加上limit,这个问题就可以解决了。对于8.0及以上的版本,可以使用NO_MERGE特性来解决这个问题。