MySQL 架构与内部模块(四)

106 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情

执行引擎(Execution Engine),返回结果

执行器,或者叫执行引擎,它利用存储引擎提供的相应的 API 来完成操作。最后把数据返回给客户端,即使没有结果也要返回。

MySQL 体系结构总结

模块详解

image.png

1、 Connector:用来支持各种语言和 SQL 的交互,比如 PHP,Python,Java 的JDBC;

2、 Management Serveices & Utilities:系统管理和控制工具,包括备份恢复、MySQL 复制、集群等等;

3、 Connection Pool:连接池,管理需要缓冲的资源,包括用户密码权限线程等等;

4、 SQL Interface:用来接收用户的 SQL 命令,返回用户需要的查询结果

5、 Parser:用来解析 SQL 语句;

6、 Optimizer:查询优化器;

7、 Cache and Buffer:查询缓存,除了行记录的缓存之外,还有表缓存,Key 缓存,权限缓存等等;

8、 Pluggable Storage Engines:插件式存储引擎,它提供 API 给服务层使用,跟具体的文件打交道。

架构分层

总体上,我们可以把 MySQL 分成两层,执行操作的服务层,和存储管理数据的存储引擎层(参考 MyBatis:接口、核心、基础)。

image.png

服务层

包括客户端跟服务端的连接,查询缓存的判断、对 SQL 语句进行词法和语法的解析(比如关键字怎么识别,别名怎么识别,语法有没有错误等等)。

然后就是优化器,MySQL 底层会根据一定的规则对我们的 SQL 语句进行优化,最后再交给执行器去执行。

存储引擎

存储引擎就是我们的数据真正存放的地方,在 MySQL 里面支持不同的存储引擎。再往下就是文件管理系统,内存或者磁盘。

一条更新 SQL 是如何执行的?

更新流程和查询流程有什么不同呢?基本流程也是一致的,也就是说,它也要经过解析器、优化器的处理,最后交给执行器。

区别就在于拿到符合条件的数据之后的操作。

缓冲池 Buffer Pool

首先,对于 InnoDB 存储引擎来说,数据都是放在磁盘上的,存储引擎要操作数据,必须先把磁盘里面的数据加载到内存里面才可以操作。

这里就有个问题,是不是我们需要的数据多大,我们就一次从磁盘加载多少数据到内存呢?磁盘 I/O 的读写相对于内存的操作来说是很慢的。如果我们需要的数据分散在磁盘的不同的地方,那就意味着会产生很多次的 I/O 操作。

所以,无论是操作系统也好,还是存储引擎也好,都有一个预读取的概念。也就是说,当磁盘上的一块数据被读取的时候,很有可能它附近的位置也会马上被读取到,这个就叫做局部性原理。那么这样,我们干脆每次多读取一点,而不是用多少读多少。

InnoDB 设定了一个存储引擎从磁盘读取数据到内存的最小的单位,叫做页。操作系统也有页的概念。操作系统的页大小一般是 4K,而在 InnoDB 里面,这个最小的单位默认是 16KB 大小,它是一个逻辑单位。如果要修改这个值的大小,必须修改源码重新编译安装。

我们要操作的数据就在这样的页里面,数据所在的页叫数据页。

设想一下:如果对于数据页的操作,每次都直接操作磁盘,从磁盘加载到内存,这样会不会很慢?能不能把这些页缓存起来呢?

InnoDB 使用了一种缓冲池的技术,也就是把磁盘读到的页放到一块内存区域里面。下一次读取相同的页,先判断是不是在这个内存区域里面,如果是,就直接读取,然后操作,不用再次从磁盘加载。

这个内存区域就叫 Buffer Pool

image.png

修改数据的时候,先修改内存缓冲池里面的页。内存的数据页和磁盘数据不一致的时候,我们把它叫做脏页。那脏页什么时候同步到磁盘呢?

InnoDB 里面有专门的后台线程把 Buffer Pool 的数据写入到磁盘,每隔一段时间就一次性地把多个修改写入磁盘,这个动作就叫做刷脏