MySQL基础架构

MySQL主要分作Server层引擎层

  • Server层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图、函数等,另还有一个通过的日志模块-binlog日志模块;
    • 连接器:身份认证和权限相关
    • 查询缓存:执行查询语句的时候,会先查询缓存「MySQL8.0版本被移除」
    • 分析器:没有命中缓存的话,SQL语句就需要先经过分析器进行分析。分析SQL语句要干嘛,以及检查SQL语句语法是否合法
    • 优化器:将语句按照MySQL觉得最优解的方式进行执行
  • 存储引擎:主要负责数据的存储和读取,采用可以替换的插件式架构,支持InnoDB、MyISAM。Memory等多个存储引擎,其中InnoDB引擎有自有的日志模块-redo log模块。现在最常用的存储引擎是InnoDB,自MySQL5.5.5就被设置为默认存储引擎了。

    Server层

    连接器

    连接器主要负责身份认证和权限相关的功能,就和一个功能性的门卫一样。
    主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。

    查询缓存

    查询缓存主要用来缓存我们所执行的select语句和其结果集。属于MySQL8.0已移除的功能。
    连接建立后,执行查询语句的时候,会优先查询缓存,MySQL 会先校验这个SQL是否执行过,执行过的话会以Key-Value的形式缓存在内存中,Key是查询语句,Value是结果集。如果缓存key被命中,就会直接结果集返回给客户端,如果没有命中,就会执行后续的操作,完成后也会把结果集缓存起来,方便下一次调用。
    当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询权限。
    MySQL 查询不建议使用缓存,因为查询缓存失效在实际业务场景中可能会非常频繁,假如你对一个表更新的话,这个表上的所有的查询缓存都会被清空「热点数据缓存极其容易失效」。对于不经常更新的数据来说,使用缓存还是可以的。

    分析器

    如果MySQL没有命中缓存,那么语句会进入分析器,分析器主要是用来分析SQL的作用,步骤会分为以下几步:
  1. 词法分析:一句SQL由多个字符串组成。首先提取关键字「select之类的」,提取表名,提取字段名,提取查询条件等,完成后然后进入下一步;
  2. 语法分析:判断SQL是否正确,是否符合MySQL的语法。

完成分析器的这两步之后,MySQL就准备开始执行了,为了保证最好的执行效果,此时就需要优化器的帮助了。

优化器

优化器的作用就是让SQL语句按照它认为的最优解进行执行(它认为的不一定是实际上的),比如多个索引的时候如何选择使用索引,多表查询的时候如何选择关联顺序等。
经过优化器的优化之后,该语句的执行就已经确定了。

执行器

确定了执行顺序之后,MySQL就准备开始执行了。首先会校验用户权限是否合法,若没有对应权限就会返回错误信息。
如果有权限就会去调用引擎的接口,返回接口执行的结果。

实例分析

大体上SQL语句「DDL」可以分作两种,其一是查询「SELECT」,其二是增删改「INSERT / DELETE / UPDATE」,我们逐一来示例分析。

查询语句分析

实例SQL如下:

  1. SELECT * FROM t_student a WHERE a.age = 18 AND a.name = '张三';
  1. 结合前文,我们推断这句SQL的执行流程如下:
  1. 校验权限
    1. 如果用户没有权限则返回报错;
    2. (MySQL8.0之前)如果用户有权限有权限则查询缓存,若缓存命中则返回缓存中的结果集;
    3. (MySQL8.0及之后)若缓存未命中,则进行下一步;
  2. 词法分析
    1. SQL语句交由分析器进行词法分析,提取SQL语句的关键元素;
    2. 检查SQL语句是否有语法错误,若有则返回报错,若没有则进行下一步;
  3. 优化执行
    1. 根据词法分析,可能有以下两种执行方案
      1. 查询姓名为张三的学生中,年龄为18的学生
      2. 查询年龄为18的学生中,姓名为张三的学生
    2. 优化器根据自己的优化算法选择执行效率最高的一个方案(它认为的不一定是实际上的)
    3. 进行权限校验,如果没有权限就返回错误信息,有权限则调用引擎接口,返回引擎的执行结果

      更新语句分析

      实例SQL如下:
      1. UPDATE t_student a SET a.age = 19 WHERE a.name = '赵四';
      更新语句的基本流程和查询语句基本一致,不过在此之外引入了日志模块。
      大致流程如下:
  • 查询:先查询到赵四这条数据,若有缓存,也会优先查询缓存;
  • 修改&记录日志
    • 拿到查询到的记录后,进行修改,把赵四的年龄改为19,然后调用引擎API,写入这一行数据,让InnoDB把数据保存到内存中;
    • 同时记录重做日志,同时将重做日志设置到prepare状态,然后告诉执行执行完毕,随时可以提交;
  • 执行:执行器收到通知后,记录binlog,然后调用引擎API,将重做日志设置为commit状态
  • 完成

    总结

    MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(bin log),这个日志模块所有执行引擎都可以共用,redo log 只有 InnoDB 有。

    引擎层是插件式的,目前主要包括:MyISAM、InnoDB、Memory 等。 查询语句的执行流程如下:
    MySQL语句执行流程 - 图1

更新语句执行流程如下:
MySQL语句执行流程 - 图2