全国协议5人面授小班,企业级独立开发考核,转业者的IT软件工程师基地 登录/注册 | 如何报名
当前位置: 数据库   >  MySQL 逻辑架构
admin · 更新于 2021-08-05

1. 逻辑架构组成

\上方是 MySQL 逻辑架构的简单示意图,总的来说,MySQL 包含 Server 层和存储引擎层两大部分。

Server 层包括连接池、查询缓存、解析器、优化器、执行器等,MySQL 的核心服务都在这一层。

存储引擎层负责数据的存储和提取,MySQL 采用插件式的存储引擎,常见的存储引擎有 InnoDB、MyISAM、 CSV 等。其中 InnoDB 是最常用的存储引擎,也是 MySQL 的默认存储引擎(从5.5.5版本开始)。

2. 一条查询语句是如何执行的

上一小节介绍了 MySQL 的逻辑架构组成,那么各模块之间是如何协同工作的呢?这里以一条最简单的查询语句为例子,我们一起来看看这条语句在 MySQL 内部是如何执行的。

select id from a where id=1;
代码块
  • 1

2.1 连接池

首先,我们通过 mysql 这个客户端工具进行数据库的连接,这时遇到的是连接池。连接池负责客户端的连接管理、授权认证。

连接命令如下(输入完连接命令后,需要输入用户密码):

mysql -h localhost -u root -p
代码块
  • 1
  • 如果用户名和密码认证通过,连接池会通过权限表获取这个用户名所拥有的权限信息;

  • 如果用户名或密码认证不通过,则会收到一个错误提示:“ERROR 1045 (28000): Access denied for user ‘root’@‘localhost’”;

建立连接后,会产生相应的连接信息,可以通过 show processlist 命令查看。下方图中 Id 为 5048 这一行,即为成功连接数据库所建立的连接信息,请注意 Command 这一列,值为”Sleep“,表明这是一个空闲连接。成功连接数据库后,如果没有任何动作,这个连接就会变成空闲状态。

root@localhost [(none)]>show processlist;+------+------+-----------+------+---------+------+----------+------------------+| Id   | User | Host      | db   | Command | Time | State    | Info             |+------+------+-----------+------+---------+------+----------+------------------+| 4771 | root | localhost | NULL | Query   |    0 | starting | show processlist || 5048 | root | localhost | NULL | Sleep   |    3 |          | NULL             |+------+------+-----------+------+---------+------+----------+------------------+2 rows in set (0.00 sec)
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.2 查询缓存

连接成功建立后,来到第二步查询缓存。查询缓存负责将执行过的语句和结果缓存在内存中。

在获取一个查询请求后,MySQL会先到查询缓存进行查看

  • 如果select语句在查询缓存中能够找到,则直接返回结果给客户端,跳过解析、优化、执行阶段。
  • 如果select语句没能在查询缓存中找到,则继续后面的解析、优化、执行阶段。

从这里可以看到,如果命中查询缓存,MySQL 会直接返回结果给客户端,后面的一系列操作不需要再执行,是非常高效的。但实际情况并非如此,查询缓存非常容易失效

因为只要一个表有更新操作,那这个表所有的查询缓存都会被清空。对一个承载正常业务的数据库来说,更新操作是非常频繁的,这就意味着查询缓存经常失效,从而导致查询缓存的命中率非常低。所以,使用查询缓存反而会给数据库带来额外的负担,在实际生产环境中,我们建议关闭查询缓存

关闭查询缓存的方法有两种:

  • 临时:在 MySQL 中直接用命令行执行;

    set global query_cache_size=0set global query_cache_type=0
    代码块
    • 1
    • 2
  • 永久:将以下两个参数添加至配置文件 my.cnf,并重启 MySQL;

    query_cache_type=0query_cache_size=0
    代码块
    • 1
    • 2

2.3 解析器

如果没有命中查询缓存,接下来就要进入解析器阶段了。解析器负责词法解析和语法解析。

首先是词法解析,MySQL 需要识别所输入的字符串分别代表什么,它会从左到右一个字符、一个字符地输入,然后根据构词规则识别单词。

select id from a where id=1;
代码块
  • 1
关键字非关键字关键字非关键字关键字非关键字
select字段idfrom表名awhere字段id等于1

接下来是语法解析,判断输入的这个SQL语句是否符合MySQL语法规则。如果语法不对,会收到错误信息提示:“ERROR 1064 (42000): You have an error in your SQL syntax;”。如下面这个SQL语句的where少了一个e。

root@localhost [tempdb]>select id from a wher id=1;ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'id=1' at line 1
代码块
  • 1
  • 2

2.4 优化器

从解析器出来,就到了优化器阶段。优化器负责找到最优的执行计划,也就是决定SQL语句的执行方案。

一条查询可以有很多种执行方式,最后都返回相同的结果 。比如下面这个查询SQL,查询表a中字段id等于1的值

select id from a where id=1;
代码块
  • 1
  • 可以遍历表a所有行,找出所有id等于1的值
  • 也可以通过索引idx_id,找到id等于1的值。当然,前提是字段id有创建索引idx_id。

两种方案的结果是一样的,但是执行效率不一样,优化器的作用就是选择最优的执行方案。

2.5 执行器

现在到了执行SQL语句的阶段,也就是执行器。执行器负责调用存储引擎,拿到查询结果。

select id from a where id=1;
代码块
  • 1
  • 2

假设这个例子中的字段id没有索引,执行器的流程大致如下:

  1. 调用 InnoDB 引擎接口获取表 a 的第一行,如果 id 值等于 1,则将 id 值存进结果集,如果 id 值不等于 1,则跳过,取下一行;
  2. 调用 InnoDB 引擎接口获取下一行,重复第一步的逻辑,一直到表 a 的最后一行;
  3. 将符合查询条件的结果集返回给客户端。

3. 小结

一条 SQL 查询的过程,大致就是这样的流程:连接池、查询缓存、解析器、优化器、执行器。

连接池负责连接管理,查询缓存建议关闭,解析器让 MySQL 知道要做什么,优化器让 MySQL 知道怎么做,执行器负责执行取数。

通过本文的讲解,对您认识 MySQL 逻辑架构,有所帮助吗?欢迎反馈宝贵意见,以便我们不断改进。


为什么选择汉码未来