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.

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
Ubuntu 关系型数据库 MySQL
MySQL源码编译安装
本文详细介绍了MySQL 8.0及8.4版本的源码编译安装全过程,涵盖用户创建、依赖安装、cmake配置、编译优化等步骤,并提供支持多Linux发行版的一键安装脚本,适用于定制化数据库部署需求。
2662 4
MySQL源码编译安装
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
1091 6
|
SQL 关系型数据库 MySQL
Mysql基础学习day01
本课程为MySQL基础学习第一天内容,涵盖MySQL概述、安装、SQL简介及其分类(DDL、DML、DQL、DCL)、数据库操作(查询、创建、使用、删除)及表操作(创建、约束、数据类型)。适合初学者入门学习数据库基本概念和操作方法。
367 6
|
关系型数据库 MySQL 数据管理
Mysql基础学习day03-作业
本内容包含数据库建表语句及多表查询示例,涵盖内连接、外连接、子查询及聚合统计,适用于员工与部门数据管理场景。
244 1
|
SQL 关系型数据库 MySQL
Mysql基础学习day02-作业
本教程介绍了数据库表的创建与管理操作,包括创建员工表、插入测试数据、删除记录、更新数据以及多种查询操作,涵盖了SQL语句的基本使用方法,适合初学者学习数据库操作基础。
262 0
|
SQL 关系型数据库 MySQL
Mysql基础学习day03
本课程为MySQL基础学习第三天内容,主要讲解多表关系与多表查询。内容涵盖物理外键与逻辑外键的区别、一对多、一对一及多对多关系的实现方式,以及内连接、外连接、子查询等多表查询方法,并通过具体案例演示SQL语句的编写与应用。
323 0
|
SQL 关系型数据库 MySQL
Mysql基础学习day01-作业
本教程包含三个数据库表的创建练习:学生表(student)要求具备主键、自增长、非空、默认值及唯一约束;课程表(course)定义主键、非空唯一字段及数值精度限制;员工表(employee)包含自增主键、非空字段、默认值、唯一电话号及日期时间类型字段。每个表的结构设计均附有详细SQL代码示例。
258 0
|
SQL 关系型数据库 MySQL
Mysql基础学习day02
本课程为MySQL基础学习第二天内容,涵盖数据定义语言(DDL)的表查询、修改与删除操作,以及数据操作语言(DML)的增删改查功能。通过具体SQL语句与实例演示,帮助学习者掌握MySQL表结构操作及数据管理技巧。
312 0
|
SQL 存储 关系型数据库
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
本文详细介绍了MySQL中的SQL语法,包括数据定义(DDL)、数据操作(DML)、数据查询(DQL)和数据控制(DCL)四个主要部分。内容涵盖了创建、修改和删除数据库、表以及表字段的操作,以及通过图形化工具DataGrip进行数据库管理和查询。此外,还讲解了数据的增、删、改、查操作,以及查询语句的条件、聚合函数、分组、排序和分页等知识点。
1656 57
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
|
NoSQL 关系型数据库 MySQL
在Visual Studio Code中设置MySQL源码调试环境
以上步骤涵盖了在VS Code中设置MySQL源码调试环境的主要过程,是一个相对高级的任务,旨在为希望建立强大开发和调试环境的开发者提供指引。遵循这些步骤,将可以利用VS Code强大的编辑和调试功能来深入理解和改进MySQL数据库的底层实现。
797 0

推荐镜像

更多