给定一条SQL,你知道它是如何在MySQL中走完一个流程的吗?

给定一条SQL,说下它的执行流程吧!

画图解释

简要解释一下上图的组件

  1. 连接器:与身份认证和权限认证相关(登录mysql的时候)
  2. 查询缓存:执行sql的时候,会先去查询缓存,看看缓存中有没有(MySQL8.0之后移除了,用处不大)
  3. 分析器:在缓存没有命中的时候,会进这个分析器。说白了,就是拿到你这条sql,分析你要干嘛,并且检查以下你的语法是否正确
  4. 优化器:按照MySQL认为的最好的方案去执行这条SQL
  5. 执行器:执行语句,然后从存储引擎中获取数据。

简要解释下MySQL的分层

MySQL主要分为server层和存储引擎层

server层:它主要包括连接器、分析器、优化器、执行器等,所有跨存储引擎功能都在这一层。还有一个通用的binlog日志模块

存储引擎层:MySQL实现的各种存储引擎,包括MyISAM、InnoDB等,现在InnoDB使用的非常多,MySQL5.5.5之后,默认的存储引擎就是InnoDB

语句分析

说了这么多,一条SQL是如何执行的呢?大致可以将SQL语句分为两种:查询语句和更新语句(插入、更新、删除),先来介绍下查询语句是怎么进行的。

查询语句

给定一条SQL:

select * from t_student A where A.age=18 and A.name="张三";

MySQL拿到这条SQL会进行以下的流程:

  • 先经过连接器,查询是否有权限,如果没有权限就直接返回错误信息,如果有权限,就会去查询缓存, 如果缓存中有就直接返回,如果缓存不命中,就会走到下一步分析器中去

  • 来到分析器,它会提取这条sql的关键词:select、t_student等这些,然后做对应的操作,除了这个工作,它还会检查这条sql是否有语法错误,如果有错误也是直接返回错误信息了,如果没有错误,会进到优化器中去

  • 优化器会根据它所认为的最好的方案进行生成具体的sql方案,比如这条sql,会有两种方案

    1、先找出age = 18的数据,从这批数据中找出name=“张三”的数据
    2、先找出name = “张三”的数据,从这批数据中找出age = 18的数据
    优化器会根据它的算法得出最好的方案(但不一定是真正最优的方案),交由执行器去执行。
    
  • 最后就来到了执行器,它首先会判断有没有权限,如果没有权限的话,就返回错误信息,如果有权限的话,就会调用存储引擎的接口,然后获取数据返回给客户端。

更新语句

来给定一条SQL:

update t_student A set A.age = 19 where A.name="张三"; 

其实它的sql执行流程跟查询差不多,就是在更新的时候,会涉及到写日志的步骤,MySQL会把这条记录写到binlog(归档日志)中,所有的存储引擎都是这样的流程,但是我们常用的InnoDB还带有redo log(重做日志),也会记录redo log。下面来用InnoDB引擎来介绍下更新的流程:

  • 首先先进行查询操作,找到这条数据,期间如果有缓存命中,就从缓存中获取这条数据,拿到这条数据,将它的age改为19
  • age改为19后,InnoDB会将这条操作记录写入到redo log中,redo log进入到prepare(预提交)阶段,然后告诉执行器,执行完成了,随时可以提交。
  • 执行器收到通知,会记录bin log日志,然后调用引擎接口,将redo log修改为提交状态
  • 更新完成。

看完上面的步骤或许会有以下几条疑问

  • 为什么redo log会先进入预提交状态,而不是直接提交呢?假如我们直接将redo log进入提交状态,在还没记录bin log的时候,机器宕机了,那么就会出现问题了,redo log中的记录和bin log中的数据不一致,会导致主从复制的时候,数据不一致的情况,本机有这条数据,从机没有这条数据。所以采用预提交阶段
  • 为什么是先写redo log再写bin log?反过来不行吗?如果先写bin log的话,写完之后机器宕机了,redo log没有记录,导致这一条数据逻辑上的丢失(InnoDB找不到这条数据,但实际上是存在的)。这也是导致数据不一致的情况。
  • 只有一个bin log 记录不行吗?为什么还要加入redo log?其实这样的方案也可以,只不过加入redo log是InnoDB用来解决事务的问题的,如果不要求事务的话,只记录bin log是没有问题的。

总结

总结以下上面的笔记:

  • MySQL分为Server层和存储引擎层,Server层主要包括连接器、查询缓存、分析器、优化器、执行器等组件,同时还有一个日志模块bin log,这个日志是所有的存储引擎共用的一个日志模块。而redo log是InnoDB特有的一个用于解决事务问题的重做日志。存储引擎组包括常见MyISAM和InnoDB以及其他的存储引擎
  • 查询语句执行SQL的流程:执行器–>权限校验–>查询缓存,命中就返回,未命中–>分析器–>权限校验–>执行器–>返回结果
  • 更新语句执行SQL的流程:执行器–>权限校验–>查询缓存,命中就获取该记录–>分析器–>权限校验–>执行器–>redo log prepare–>bin log–>redo log commit

猜你喜欢

转载自blog.csdn.net/MarkusZhang/article/details/108337983