SQL在mysql中的执行过程
原文连接
SQL在mysql中的执行过程
基础架构概览
我们先总结基本组件
- 连接器: 身份认证 + 权限相关的,我们连接的时候会验证
- 查询缓存: 8.0之后移除,执行查询的时候,会先查缓存
- 分析器: 分析你的sql语句,包括词法分析 + 语法分析
- 优化器: 按照mysql认为最优的方案去执行
- 执行器: 执行语句,然后从存储引擎中返回数据
对于mysql总的来说,分为两个模块,一个是Server层,一个是存储引擎层
- Server层,包括连接器,分析器,优化器,执行器,查询缓存,所有跨存储引擎的功能都是在这里实现的,例如函数 + 触发器 + 存储过程 + 视图,还有一个binglog日志模块
- 存储引擎层,就是我们熟知的innodb,或者是myisam
Server层组件介绍
连接器
类似于保安,进行用户认证,包括账号密码 + 权限,如果验证通过,会去查该用户下的所有权限,之后的权限判断都是按照这个地方查到的权限,所以,理论上来说,连接不断的化,就算改了该用户的权限,也可以用.
查询缓存
8.0之后,被删除了,原因是经常不命中,这个功能本来就很鸡肋,缓存的化,可以用很多东西进行代替,mysql这里的缓存可是所有语句所以,很多时候不会命中,也说得过去.
它的执行流程是,来了一个查询,查缓存是否有,缓存中存储形式为key-value
key是查询语句,value是结果
有缓存的化,返回
没有缓存的化,去查数据库,然后会把结果加入到缓存中
分析器
分析你的sql是干嘛的
- 词法分析: 词法,单词的用法,也就是看你的select,查的是什么表,查询条件是什么
- 语法分析: 看你的sql是否合法
为什么要有词法分析呢? 因为我们后边要优化啊,你都不知道sql要干嘛怎么优化?
优化器
优化器的作用就是选一条mysql自己认为最优的路,这个就大有学问了,必须得学索引相关,才能入门,这个时候会生成一个执行计划给到执行器
执行器
先看用户是否有权限,有的化,调用存储引擎的接口,返回结果
流程
对于查询语句来说,不会涉及到数据的更改,所以不用记录查询日志
对于更新操作来说,需要更新日志
查询流程
- 先看是否有缓存
- 分析器,词法分析+ 语法分析
- 优化器,生成执行计划
- 执行器,执行,调用存储引擎接口,返回结果
更新流程
对于更新语句,基本的流程和查询一致
不同的是,执行更新的时候,会记录日志
mysql自带的是binlog归档日志,innodb带的是redo log
update tb_student A set A.age='19' where A.name=' 张三 ';
- 先查缓存,有缓存,返回结果
- 然后拿到查询的语句,执行查询,调用引擎api,执行写入数据,innodb引擎会把数据保存在内存中,同时记录redo log,此时redo log进入prepare状态,然后告诉执行器,随时可以提交
- 执行器收到之后记录binlog,提交redo log为提交状态
总结一致性问题
一致性问题的出现在于,我们考虑到可能发生的宕机异常,此时就容易有一致性问题
我们这里的流程是先写redo log,设置为prepare状态,然后再写binlog,最后提交redo log,这个流程很合理,因为它解决了一致性问题,为了展示这个方案的合理性,我们用反证法来看
假设,我们先写redo log,直接提交,再写binlog
如果,redo log写完提交之后,宕机了,恢复的时候,redo log里边有记录,binlog里边没有记录,之后主从同步的时候,就丢失了这个数据了,一致性问题出现
假设我们先写binlog,再写redo log
先写binlog,写完之后,宕机,恢复的时候,binlog里边有记录,redo log里边没有记录,无法恢复这条数据,也是一致性问题
对于此,redo log的两阶段提交的方式就比较合理,我们来正着来看这个方案的合理之处
假设写完redo log,此时处于prepare状态,宕机了,恢复的时候,binlog没有,redolog 有,可以做回滚操作,没有一致性问题
假设写完redo log ,此时处于prepare状态,再写binlog,写完binlog,宕机了,恢复的时候,此时就要依赖于MySQL的处理过程:
- 判断redo log是否完整,如果完整,就直接提交
- 如果redo log只是预提交,没有commit的化,判断binlog是否完整,如果完整提交redo log,不完整回滚
总结
查询语句的执行流程: 权限校验 查询缓存 -> 分析器 -> 优化器 -> 权限校验
更新语句的执行流程: 分析器 -> 权限校验 -> 执行器 -> 引擎 -> redo log(prepare) -> binglog -> redo-log (commit)