须要从数据库检索某些符合要求的数据,咱们很容易写出 Select A B C FROM T WHERE ID = XX 这样的SQL,那么当咱们向数据库发送这样一个请求时,数据库到底作了什么?java
咱们今天以MYSQL为例,揭示一下MySQL数据库的查询过程,并让你们对数据库里的一些零件有所了解。mysql
MYSQL架构

mysql架构程序员
MySQL 主要能够分为 Server 层和存储引擎层。算法
Server层 包括链接器、查询缓存、分析器、优化器、执行器等,全部跨存储引擎的功能都在这一层实现,好比存储过程、触发器、视图、函数等,还有个通用的日志模块binlog日志模块;sql
存储引擎层 负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。如今最经常使用的存储引擎是 InnoDB(支持事务),它从 MySQL5.5.5 版本开始成为默认存储引擎。数据库
链接器
链接器主要负责用户登陆数据库,进行用户的身份认证,包括校验帐户密码,权限等操做。缓存
若是用户密码不对,你就会收到一个"Access denied for user"的错误,而后客户端程序结束执行。微信
若是用户帐户密码已经过,链接器会到权限表中查询该用户的全部权限,以后在这个链接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个链接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。数据结构
查询缓存( Query cache)
客户端与服务端创建链接后,MySQL 在执行查询语句时会先查询缓存,校验这条SQL是否是在以前执行过。以前执行过的语句及其结果会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果。若是你的查询可以直接在这个缓存中找到 key,那么这个value 就会被直接返回给客户端。若是没有命中,则须要执行后续的操做,完成后也会把结果缓存起来,方便下一次调用。架构
看到这里你们会不会眼前一亮,会不会有这个功能很好要好好利用的冲动。
其实这里并不建议使用查询缓存,查询缓存的失效很是频繁,只要有对一个表的更新,这个表上全部的查询缓存都会被清空。所以极可能你费劲地把结果存起来,还没使用就被一个更新全清空了。对于更新压力大的数据库来讲,查询缓存的命中率会很是低。除非是那种很长时间不会更新的表,好比系统配置表,可是这种系统配置咱们放在配置平台很差吗?
在MYSQL8.0中已经删除了查询缓存这个功能,官方也是认为该功能在实际的应用场景比较少,因此干脆直接删掉了。
分析器
Mysql没有命中查询缓存,那么就会进入分析器,分析器主要是用来分析SQL语句是来干吗的。分析器主要分为如下两步:
-
词法分析 :一条SQL语句有多个字符串组成,首先要提取关键字,好比select,提出查询的表,提出字段名,提出查询条件等等。
-
语法分析:根据词法分析的结果,语法分析主要就是判断你输入的SQL语句是否正确,是否符合MYSQL语法,若是你的语句不对,就会收到“You have an error in your SQL syntax”的错误提醒。
词法分析程序将整个查询语句分解成各种标志,语法分析根据定义的系统语言将“各种标志”转为对MySQL有意义的组合。最后系统生成一个语法树(AST),语法树即是优化器依赖的数据结构。
优化器
通过了分析器,MySQL 就知道你要作什么了。在开始执行以前,还要先通过优化器的处理。
为何须要优化器?
-
优化器中包含了许多 复杂的优化技术,这些优化技术每每比最好的程序员掌握的还要多。系统的自动优化至关于使得全部人都拥有这些优化技术。
-
优化器能够从数据字典中获取许多 统计信息,例如表中的行数、表中的每一个列的分布状况等。优化器优化器能够考虑百种不一样的执行计划,而程序员通常只能考虑有限的几种可能;
-
能够根据这些信息选择 有效的执行计划,而用户程序则难以得到这些信息;
总之优化器是对语法分析树的形态进行修改,把语法分析树变为查询树,肯定执行方案。
执行器
MySQL 经过分析器知道了你要作什么,经过优化器知道了该怎么作,因而就进入了执行器阶段,开始执行语句。
开始执行的时候,要先校验改用户是否有执行查询的权限,若是没有,就会返回没有权限的错误。若是有权限,就会去调用引擎的接口,返回接口执行的结果。
语句分析
咱们如下面一条真实SQL查询语句来进行分析下MYSQL查询的执行过程
select id,name,sex,phoone from user t where t.age='26' and t.account='javadaily'
-
首先客户端须要链接上数据库,若是帐号密码错误直接返回错误信息,若是正确则进入下一步。
-
在MYSQL8.0以前会先去查询缓存中,以这条SQL语句做为key在内存中查询是否有结果,若是有则先判断是否有权限,有权限则返回客户端,不然报错;若是没有从查询缓存命中则进入下一步
-
经过分析器进行词法分析,提取sql语句的关键元素,好比提取上面这个语句是查询select,提取须要查询的表名为
user
,须要查询的列为id,name,sex,phoone
,查询条件是age=26
和account=javadailly
。而后判断这个sql语句是否有语法错误,好比关键词是否正确等等,若是检查没问题就执行下一步。
-
上面的SQL有两种执行方案,优化器根据本身的优化算法选择执行效率最高的a方案(统计信息不许可能致使优化器选择错误的执行方案),肯定了优化方案后就开始执行。
a. 先查询account=javadaily
的用户,而后判断age
是否等于26
b. 先找出age=26
的用户,再查询account=javadaily
的用户
-
进行权限校验,若是有查询权限则调用数据库引擎接口返回执行结果;不然报错。
以上,但愿对你有所帮助!
这里为你们准备了一份小小的礼物,关注公众号,输入以下代码,便可得到百度网盘地址,无套路领取!
001:《程序员必读书籍》
002:《从无到有搭建中小型互联网公司后台服务架构与运维架构》
003:《互联网企业高并发解决方案》
004:《互联网架构教学视频》
006:《SpringBoot实现点餐系统》
007:《SpringSecurity实战视频》
008:《Hadoop实战教学视频》
009:《腾讯2019Techo开发者大会PPT》
010: 微信交流群
本文分享自微信公众号 - JAVA日知录(javadaily)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。