从查询语句执行流程看MySQL架构

常言道,看待一个事情要先知全貌,从高维度认识、理解,然后再深入各个细节,一一击破。MySQL的学习也不例外,那么你知道一条SQL在MySQL中执行要经历哪些步骤吗?每个步骤都有MySQL的哪些“零件”参与吗?如果不清楚的话,可以阅读本文。

SQL执行流程

在MySQL客户端或者JAVA应用程序中查询一条最简单的语句比如select * from T where ID =10;你知道经历哪些步骤吗?

从查询语句执行流程看MySQL架构_第1张图片

连接

你要执行查询语句前肯定要先和MySQL建立连接啊,那怎么建立连接呢?

可以通过下面的命令:

mysql -h ip -P port -u$user -p
复制代码
  • 经过三次握手建立连接成功后, 验证客户端传来的连接用户名和密码,并不是任何阿猫阿狗都可以连啊
  • 如果用户名或密码不对,会收到一个Access denied for user错误,客户端程序结束执行
  • 用户名密码认证通过,会从权限表查出账号拥有的权限与连接关联,之后的权限判断逻辑,都将依赖于此时读到的权限

这个用于连接的“零件”就是MySQL的连接器,它主要负责跟客户端建立连接、获取权限、维持和管理连接。

查缓存

现在连接建立好了,相当于客户端和MySQL服务端的“传输管道”有了,开始查数据了。

都说性能不够,缓存来凑,MySQL“为了性能”,也实现了查询缓存。

  • MySQL以查询的语句作为key去查询缓存中获取对应的value
  • 如果没有的话,会去做真实的查询
  • 如果有的话,直接返回缓存中的数据
  • 如果这个表发生更新,查询缓存会清空

所以关键点在于MySQL表的更新频率以及缓存的命中率,我们可以根据下面命令查看监控查询缓存:

show status like '%Qcache%';
复制代码

从查询语句执行流程看MySQL架构_第2张图片

  • Qcache_hits: 表示有 多少次命中缓存。我们主要可以通过该值来验证我们的查询缓存的效果。数字越大,缓存效果越理想。
  • Qcache_inserts: 表示多少次未命中然后插入,意思是新来的SQL请求在缓存中未找到,不得不执行查询处理,执行查询处理后把结果insert到查询缓存中。这样的情况的次数越多,表示查询缓存应用到的比较少,效果也就不理想。当然系统刚启动后,查询缓存是空的,这也正常。

这上面一个过程就是MySQL的查询缓存操作。

但是实际情况是查询缓存往往弊大于利,因为查询缓存的失效非常频繁,一般建议大家在静态表里使用查询缓存。但是在MySQL 8.0中已经去掉了查询缓存。

分析验证

如果没有命中查询缓存,就要开始真正去查了。在查询前,MySQL肯定要“理解”你这条SQL语句啊,所以要有个“零件”去分析验证你的SQL语句,那究竟是怎么个分析过程呢?

  1. 词法分析, 你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面 的字符串分别是什么,代表什么。
  2. 语法分析,根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个SQL语句是否满足 MySQL语法。

这也是为什么我们的SQL语句存在语法问题的时候会报错,就是这个叫做分析器的零件报出来的。

从查询语句执行流程看MySQL架构_第3张图片

优化

语法没问题,就够了吗?当然不够,智能的MySQL还要帮我们做优化,那都做哪方面的优化呢?

  1. 比如有多个索引的时候,智能选择一个它认为最佳的索引
  2. 多表关联的时候,决定表的连接顺序
  3. 对子查询进行优化
  4. 对连接语义进行了外连接消除、嵌套连接消除....

这个过程就是由MySQL的优化器做的。

执行

优化器阶段完成后,这个语句的执行方案就确定下来了,然后真正的开始执行了。

在执行之前需要判断该用户是否具备权限 。如果没有,就会返回权限错误。如果具备权限,就执行 SQL 查询并返回结果。

我们以一开始的查询语句select * from T where ID =10;为例,ID没有索引,并且采用的innoDB作为存储引擎,整体查询的流程如下:

  • 调用 InnoDB 存储引擎接口取这个表的第一行,判断 ID 值是不是1
  • 如果不是则跳过
  • 如果是则将这行存在结果集中
  • 调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。

上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户,这一个过程就是由MySQL的执行器执行的。

MySQL逻辑架构

上面讲解了查询语句的真个执行流程,涉及了MySQL的各个“零件”,我们将这些零件组装组装,可以形成下面的逻辑架构图:

从查询语句执行流程看MySQL架构_第4张图片

大体来说,MySQL可以分为Server层存储引擎层两部分。

  • Server层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
  • 存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDBMyISAMMemory 等多个存储引擎。所有的存储引擎都共用同一个Server层。

总结

本文通过以一个查询语句的执行流程为例,讲解了MySQL整体的逻辑架构,对MySQL的各个部分有了一个全局的认知。这样,在遇到问题的时候,也比较有针对性,比如对于一个select * from T where k=1,报了Unknown column ‘k’ in ‘where clause’的错误,我们就很快的知道是分析器报出来的,因为分析器会分析我们SQL的语法。

你可能感兴趣的:(java,mysql,架构,java)