MySQL基本架构
下面来一张MySQL的基本架构图。

这张图上列举了MySQL的各个组件,并且简单的介绍了各个组件的功能。一般对MySQL的所有组件进行分析时,一般把它的组件抽象成两层。
1. Server层
包括连接器,查询缓存,分析器,优化器,执行器等。涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期,时间,数学和加密函数层),所有跨存储引擎层的功能都在这一层实现,比如存储过程,触发器,视图等。
2. 存储引擎层
存储引擎层负责数据的存储和提取,其架构模式是插件式的,支持InnoDB,MyISAM,Memory等多个存储引擎。从MySQL5.5.5版本开始,成为了默认的存储引擎。
了解了整个体系的组件和架构,我们就可以使用一条简单的SQL,把上面所有组件的流程走一遍,来看看各个组件到底是干的啥事儿。
MySQL语句如下,意思很简单,就是找一找user表里面name为二狗的记录
首先,是客户端需要先和MySQL服务端建立连接,对应在Java代码里面,如下所示:
对应在我们平时正常使用命令行连接数据库就是:
客户端在发起连接请求后,就会通过经典的TCP三次握手和连接器建立连接,在建立连接的时候连接器负责对用户名和密码进行校验,不对就会报错。除此之外,建立连接之后MySQL在整个执行过程中产生的数据都存储在连接器里面的连接对象中。所以连接时间过长的话连接对象就会太大,这是我们开发过程中需要考虑的点。
走过连接器后,就来到了查询缓存,查询缓存是(查询语句,查询结果集)的键值对。如果查询缓存里面有对应的结果集,就拿出对应的结果集,然后查看当前用户是否有权限访问该查询的数据,如果有就报错,没有就直接返回。当然,并不是每一条查询都要通过查询缓存的,可以设置query_cache_type参数为DEMAND,这样,默认的SQL都不使用查询缓存。
如果走查询缓存的话,会有缓存并没有命中的情况,这个时候就轮到分析器出马啦!!!
这个时候拿user字符串解析成user表,把字符串name识别为列name。词法解析之后就进行语法分析,如果语法不满足SQL规范,那么,不好意思,照样报错。
如果顺利的走过了分析器这关,那么就轮到优化器来发功了。词法和语法都分析了,优化器还干啥呢?
优化器当然是来优化的啦,当然,在我们这个简单的SQL查询中是看不出优化的痕迹的,不过通过下面这条SQL语句的分析,大家就懂这个意思了。
在上面这条语句里面,逻辑结果相同的情况下,有两种执行顺序:
先执行t1.id = 10,之后再执行t2.id = 30;先执行t2.id = 30,之后再执行t1.id = 10;这两种不同的顺序,造成的资源消耗是不同的,优化器就会选择使用哪一种顺序进行查询。
经过优化器,就来到Server层的最后一关:执行器
执行器拿着解析好的SQL执行,调用存储引擎的IO接口,完成表记录的读取,针对select * from user where name = 二狗这条SQL,执行器会取user表的第一行,判断name是否等于二狗,如果是,就把这条记录放在结果集里面,如果不是,就跳过当前记录,取下一行,重复判断name是否等于二狗,知道表的最后一行,最后将所有满足条件的记录组成的结果集返回给客户端。
就这样,MySQL的各个组件,以及他们干啥活,就基本讲完啦,欢迎大家补充。
MySQL存储
从MySQL的基本组件结构分析起能够建立一个宏观上的认识,可这还不够。把视角拉到程序和数据库的交互过程中来,数据库存储数据的结构到底是什么样子呢?数据库又如何把内部的数据展示给数据库外层的程序呢?我们从数据库里面经常看到的是一条一条的记录,可是数据库传入内存的并不是一条一条的记录。而是类似多条记录的一个集合,Page。中文翻译为页。页是数据库里面磁盘和内存之间交互的基本存储单位。
当从数据库中读取磁盘的数据的时候,由于磁盘和内存之间的速度是由有数量级的差距的。一条一条的从磁盘读取多条记录,还不如直接读取一批记录到内存中,再从这批记录里面取数据快。所以就有页的诞生了。但是页并不只是有多条记录,它也有自己对应的数据结构。

一个页大小一般是16KB,这16KB的空间在逻辑上可以分成7个部分,这七个部分所保存的数据在图上都有展示,详细解释,可以阅读这篇文章。
当然,当我们从MySQL中取出一条记录的时候,把页读到内存中。还需要从页里面取出指定的一条记录,这个时候需要使用PageDirectory。PageDirectory的作用就相当于页里面所有记录的一个目录,通过这个目录,就可以找到指定的记录。
当然,MySQL里面和内存交互的最小单位是页,可是我们需要的是一条单个的记录,对于页中的记录,才是真正的核心的数据的所在,下面就是一条记录的数据结构。

一条记录分为记录的额外信息和记录的真实数据两部分,记录的额外信息里面比较重要的就是记录头信息,记录的真实数据就是我们在表中插入的实际数据。
记录头信息里面的几个字段的含义如下:
记录头信息字段含义deleted_flag物理删除的标志(1:已经删除;0:未删除)min_rec_flagB+树每层非一字节点中标识最小的目录项记录n_owned把一个页划分各n个组,每个组里面的大哥会保存该值,该值表示一个组里面有多少条记录heap_no堆号,每条插入的记录都会分配堆号,默认heap_no=2开始,infimum的heap_no=0,Suprenum的heap_no=1record_type记录类型(0:普通插入的记录;1:B+树非叶子节点目录项记录;2:表示infimum的记录;3:表示Supremum的记录)next_record下一条记录(表示从当前记录的真实数据到下一条记录的真实数据的距离)记录头信息里面有一个next_record的字段,这个字段指向下一个记录的记录头信息,形成Page Directory的结构,如下图所示:

经过这一套操作,就明白了整个InnoDB这个存储引擎的最基本数据结构。
对页这个数据结构有所了解过后,再在来把视角放在内存里面,我们之前说过,MySQL从存储的最小单位是页,可是,页在内存里面是怎么放的呢?MySQL存储在磁盘里面的数据又是怎么放的呢?欢迎大家评论!!!
评论 (0)