一条SQL查询语句是如何执行的
1. 客户端服务端交互流程
其实不论客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。那服务器进程对客户端进程发送的请求做了什么处理,才能产
生最后的处理结果呢?
2. MySQL逻辑架构图
2.1 Server 层
包括连接器、查询缓存、分析器、优化器、执行器等,涵盖MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等
2.2 存储引擎层
负责数据的存储和提取,其架构模式是插件式的,支持InnoDB、MyISAM、Memory等多个存储引擎
3. 向MySQL发送一个请求
3.1 请求流程概述
- 客户端发送一条查询给服务器
- 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果,否则进入下一阶段
- 服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划
- MySQL根据优化器生成的执行计划,再调用存储引擎的API来执行查询
- 将结果返回给客户端
3.2 连接器
mysql -h$ip -P$port -u$user -p
- 如果用户名和密码不对,我们就会收到一个“Access denied for user”的错误,然后客户端程序结束执行
- 如果用户名跟密码认证通过,连接器会在权限表里查出我所拥有的权限,之后这个连接里面的权限判断逻辑,
都将依赖于此时读到的权限【取与用】
连接完成后,如果我们没有后续的动作,这个连接就处于空闲状态【show processlist】
其中的Command列显示为“Sleep”的这几行,表示现在系统里面存在几个空闲连接。
- Lost connection to MySQL server during query
客户端如果太长时间没有动静,连接器就会将它断开,这个时间是由wait_timeout控制的,默认时间是8小时【重连】
3.3 查询缓存
MySQL将缓存存放在一个引用表中,通过一个哈希值引用,这个哈希值包括了以下因素,即查询本身、当前要查询的数据库、客户端协议的版本等一些其他可能影响返回结果的信息。
-
缓存命中
请求在任何字符上的不同(例如:空格、注释、大小写)
包含系统函数、用户自定义变量和函数、一些系统表 -
缓存失效
表的结构或者数据被修改(增删改、表结构调整)
按需使用 参数query_cache_type设置成DEMAND(默认不使用查询缓存)
mysql> select SQL_CACHE * from T where ID = 10;
3.4 分析器
词法分析: select识别出查询语句,把字符串“T”识别成“表名T”,把字符串“ID”识别成“字段ID”
语法分析: 是否满足SQL的语法规则,You have an error in your SQL syntax
3.5 优化器
-
查询优化器目标:
将解析树转化成执行计划
一条查询有多种执行方法(结果相同),找到这其中最好的执行计划 -
衡量方法
基于成本的查询优化器(Cost-Based Optimizer,CBO)
尝试预测一个查询使用某种执行计划时的成本,并选择其中成本最少的一个 -
依赖:
根据优化规则对关系表达式进行转换(多执行计划)
统计信息和代价模型(成本计算)
- 示例
mysql> select * from T1 t1 join T2 t2 using(ID) where t1.c = 10 and t2.d = 20;
(1)既可以先从表t1里取出c等于10对应记录的ID值,在根据ID值关联t2表中d值等于20的记录
(2)也可以先从表t2中找到d值等于20的记录对应的ID值,在根据ID值关联t1表中c等于10的记录
这两种执行方法的结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定使用哪一种方案
统计信息的准确与否、代价模型的合理与否都会影响CBO选择最优计划
3.6 执行引擎
各种不同的存储引擎向上边的MySQL server层提供统一的调用接口(也就是存储引擎API),包含了几十个底层函数,像"读取索引第一条内容"、“读取索引下一条内容”、"插入记录"等等。
-
创建、打开和关闭表
-
对表加锁
-
全表扫描
-
通过索引访问table内容
-
事务处
-
查询权限判断
- 如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证
- 查询也会在优化器之前调用precheck验证权限
- 执行器判断一下我们对这个表T有没有执行查询的权限
-
API获取数据
(1)调用InnoDB引擎接口取这张表的第一行,判断ID是否满足条件,如果是则将结果缓存到结果集中,否则跳过
(2)调用引擎接口取“下一行”,重复相同的逻辑判断,直到取到这个表的最后一行。
(3)执行器将上述过程中筛选出来的满足条件的记录行组成的记录及作为结果集返回给客户端
3.7 返回结果给客户端
- 如果查询可以被缓存,那么MySQL在这个阶段页会将结果存放到查询缓存中
- MySQL将结果集返回给客户端是一个增量、逐步返回的过程。
- 在查询生成第一条结果时,MySQL就可以开始向客户端逐步返回结果集了
MySQL server层的核心组件:连接器、查询缓存、分析器、优化器、执行器