`
丁林.tb
  • 浏览: 802207 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

MySQL源码学习:关于整型判断的一个bug

阅读更多


问题 :

      这个 bug 来源于官方的一个 bug 报告 , 感谢 @ 印风 _ 小希 . 现象很容易描述 , 直接上例子 .  5.1 以后的版本都有此问题 .

CREATE TABLE `tb` (

  `a` int(11) DEFAULT NULL,

  `b` int(11) DEFAULT NULL,

  KEY `a` (`a`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into tb values (1,2),(2,5),(3,8),(4,6);

select * from tb force index (a) where a >=0.5;

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

| a    | b    |

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

|    2 |    5 |

|    3 |    8 |

|    4 |    6 |

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

4 rows in set (0.00 sec)


(1,2) 这个记录没有返回 .

说明一下 ,select 语句中用 force index 是以防全表扫描 . ( 不走索引 a 就正常了 ).


原因分析 :

MySQL 使用索引时 , 调用 innoDB index_read 接口 , 需要传入三个信息 : 查找的值 \ 索引 \ 查找方向 , 由于查询条件是 >=, 因此查询方向可选的是 HA_READ_AFTER_KEY HA_READ_KEY_OR_NEXT, 分别对应 > >=.

但是传入之前还要作查询优化 .

在这个例子中的流程 :

1)     MySQL 决定使用索引 a , 根据输入的值 (0.5), 取索引 [1, MAX). 之所以取 1, 是因为 a 是一个 int 类型 .;

2)     判断 0.5 1 的大小 , 0.5<1, 因此设置 tree->min_flag= NEAR_MIN; 表示实际要查找的值 , 小于传入索引范围的最小值 . 因此决定了使用 HA_READ_AFTER_KEY, 也就是 >0.5, 这没问题 .

3)     不幸的是 , 由于字段 a 是整型 , 真正传入的是 1, 逻辑变成 >1.

 

所以查找时 a=1 这个记录被忽略了 .

 

简单修改 :

      5.0 版本没这个问题 , 那时候没有 HA_READ_AFTER_KEY HA_READ_KEY_OR_NEXT 这些东西 .

      这两个值的差别只是在 innoDB 内部查找的时候要不要判断相等的那个值 , 简单的修改可以都处理为 HA_READ_KEY_OR_NEXT. 不用担心 MySQL > 变成 >= 以后的后果 , MySQL 层会再作过滤 .

 

      当然上面是偷懒的做法 , 比较正规的做法应该是在 1) 判断大小的时候 , 0.5 取整为 1, 这样判断到 1=1, 就会标记为 HA_READ_KEY_OR_NEXT.

2
0
分享到:
评论
3 楼 丁林.tb 2012-08-29  
@wj0715208
因为0.4被四舍五入成0了
2 楼 wj0715208 2012-08-25  
你好,这个我在5.1上测试的时候确实有这个bug,根据你分析的原因,来理解的话,那么>=0.4和>=0.5的出来的结果应该是一样的,但是显示的结果却是不一样的?请问我理解有什么问题?
测试的结果:
mysql> select  * from int_index force index(a) where a>=0.4;
+---+------+
| a | b    |
+---+------+
| 1 |    2 |
| 2 |    5 |
| 3 |    8 |
| 4 |    6 |
+---+------+
4 rows in set (0.00 sec)

mysql> select  * from int_index force index(a) where a>=0.5;
+---+------+
| a | b    |
+---+------+
| 2 |    5 |
| 3 |    8 |
| 4 |    6 |
+---+------+
3 rows in set (0.00 sec)
1 楼 babaoqi 2012-07-27  

我用的5.5.23版这个问题应该是已经修复了

相关推荐

Global site tag (gtag.js) - Google Analytics