文章目录

  • 前言
  • MySQL架构
  • 连接器
  • 查询缓存
  • 分析器
  • 优化器
  • 执行器
  • 存储引擎
  • 总结


前言

学习 MySQL 要先从全局角度进行宏观了解,再陷入细节里,这样能帮助我们更深入的理解细节部分。本文将讲解 MySQL 架构。



MySQL架构


mysql router 架构 mysql主流架构_查询缓存

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

Server层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。

而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持InnoDB、MyISAM、Memory等多个存储引擎。现在最常用的存储引擎是InnoDB,它从MySQL 5.5.5版本开始成为了默认存储引擎。

也就是说,你执行create table建表的时候,如果不指定引擎类型,默认使用的就是InnoDB。不过,你也可以通过指定存储引擎的类型来选择别的引擎,比如在create table语句中使用engine=memory, 来指定使用内存引擎创建表。不同存储引擎的表数据存取方式不同。

不同的存储引擎共用一个Server层,也就是从连接器到执行器的部分。你可以先对每个组件的名字有个印象,接下来依次看下每个组件的作用。



连接器

使用 MySQL ,从 Client 端首先会连接数据库,其实连接的就是连接器,连接器负责跟客户端建立连接、获取权限、维持和管理连接。连接命令如下:

mysql -h -p -u -p

上述命令发送后,会完成经典的TCP握手,连接器要开始认证身份,其实就是验证用户名密码的正确性。认证通过后,连接器会到权限表里查出你拥有的权限,此时连接后能访问的权限就依赖此时查出来的权限。

在建立连接后,如果不进行任何操作,这个连接会处于空闲状态,如果太久没有操作,连接器会自动断开连接,这个时间是由 wait_timeout 控制的,默认值是 8h

数据库中,长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接,短连接则是指每次执行完很少的几次操作就断开连接,再使用的话会新建一个连接。建立连接的过程是比较复杂的,建议减少建立连接的操作,也就是尽量使用长连接。



查询缓存

连接建立成功后,就可以对数据库做一些操作了。执行逻辑会来到第二步:查询缓存。MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句,之前执行过的语句及其结果可能会以 key-value 的形式被直接缓存在内存中, key 是查询的语句,value 是查询的结果,如果能够在缓存中找到key,则直接返回结果给客户端。

如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。你可以看到,如果查询命中缓存,MySQL不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。

但是大多数情况,不建议使用查询缓存,这是为什么?

查询缓存的弊大于利,因为查询缓存的失效非常频繁,只要对一个表有更新操作,这个表上的所有查询缓存都会被清空。对于更新压力大的数据库来说,查询缓存的命中率会非常低。表中的数据不常更新,多用于查询的情况下,才适合使用查询缓存。

可使用参数 query_cache_type 进行设置,将 query_cache_type 设置为 DEMAND,这样对于默认的 SQL 语句都不使用查询缓存,对于确定要使用查询缓存的语句,可用 SQL_CACHE 在 SQL 语句中显式指定。

select SQL_CACHE * from T where ID=10;

MySQL 8.0 直接将查询缓存删掉了,也就是说 8.0 以后彻底没有这个功能了。



分析器

上一步中如果没有命中查询缓存,就会走到分析器,开始真正执行语句了。

MySQL 需要对 SQL 进行解析,分析器会先做 “词法分析”,MySQL 需要对我们写的 SQL 进行识别,每个字符串分别代表什么。做完识别后,会做 “语法分析”,根据 “词法分析” 的结果,分析器会根据语法规则,判断输入的 SQL 是否满足 MySQL 语法。

如果存在语法错误,就会收到 ERROR 的提示信息。



优化器

经过了分析器,MySQL 会在开始执行 SQL 之前,对 SQL 进行优化。

优化器是在表中有多个索引的时候,决定使用哪个索引,或者在一个语句中有多表关联时,决定各个表的执行顺序。

select * from t1 join t2 using(ID)  where t1.c=10 and t2.d=20;

上述 SQL 中,可以先执行第一个where 条件,从 t1 中取出 c=10 的记录,再根据 ID 值关联到表 t2,在判断 t2 里面 d 的值是否等于20,也完全可以反过来执行,结果都是一样的。但是二者的执行效率不同,优化器就要在这种时候选择出最优执行方案。



执行器

优化器已经选择出了SQL 的最优执行方案,执行器就开始执行语句了。

开始执行时,会判断当前用户对要操作的表有没有权限,(如果命中查询缓存,就会在查询缓存返回结果的时候,做权限验证)如果有,就打开表执行 SQL,执行器会根据当前表定义的引擎,调用存储引擎提供的接口。

对于一个 select 语句,如果 SQL 没有使用索引,执行器是执行的:

  • 调用存储引擎接口取当前表的第一行,判断是否符合 SQL 中的条件判断,如果不是则跳过,如果是则加入到结果集中
  • 再取下一行,重复相同的判断逻辑,直到遍历完整个表
  • 执行器将上述遍历过程中查找符合条件的结果集返回给客户端

SQL 中使用索引的执行逻辑也大体相同,第一次取 “满足条件的第一行” 接口,之后循环取 “满足条件的下一个接口” ,这些接口都是存储引擎定义好的。

我们使用 EXPLAIN 分析一条 SQL 时,rows 字段可以查看当前 SQL 扫描的行数,这个值就是在执行器每次调用存储引擎获取数据行时累加的。



存储引擎

执行器中会调用存储引擎定义好的接口,而存储引擎又分为:

  • InnoDB
  • MyISAM
  • MEMORY
  • CSV
  • ARCHIVE
  • BLACKHOLE
  • MERGE

而常见的存储引擎有两种:InnoDB 和 MyISAM

总结

通过本篇文章对 MySQL 体系架构有了一定了解,关于 InnoDB 存储引擎的体系架构请跳转至: InnoDB体系架构详解

关于 MySQL 的其他文章请持续关注… …