mysql check执行流程,【MySQL数据库基础 七】MySQL架构及SQL语句执行流程

首先了解下MySQL的内部存储机制,其实我们可以把常用工具MySql workbench当做是客户端,而MySQL是服务器,结合计算机网络里学习的内容,我们可以理解为两个应用程序在通信,也就是局域网内的CS架构。

MySQL架构

客户端依据通信协议请求服务端,而MySQL这个服务器执行SQL语句命令并给出反馈,整体架构如下:

abc8beb7ad899465861f62e3f3e281a6.png

可以粗略的把MySQL服务器分为两层,上面的为Server层,主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog 日志模块:

连接器: 身份认证和权限相关(登录 MySQL 的时候),我们在数据库层执行SQL语句时,应用程序会连接到相应的数据库服务器,把SQL语句发送给服务器处理,实际上也就是通信,数据库里面,长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个

查询缓存: 执行查询语句的时候,会先查询缓存(MySQL 8.0 版本后移除,因为这个功能不太实用)。在接收到查询请求后,并不会直接去数据库查询,而是在数据库的查询缓存中找是否有相对应的查询数据(某条给定的查询语句在第一次执行时,服务器会缓存这条查询语句和他返回的结果。)

如果存在,那么在返回查询结果之前,MySQL会检查一次用户权限。如果权限没有问题,key 是查询的语句,value 是查询的结果。如果你的查询能够直接在这个缓存中找到 key,那么这个 value 就会被则直接从缓存中拿到结果返回给客户端。

查询不会被解析,不用生成执行计划,不会被执行。

判断是否命中缓存是将此查询语句和缓存中的查询语句进行比对,如果完全相同,那就认为它们是相同的,就认为命中缓存了。

如果不存在,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中

分析器: 没有命中缓存的话,SQL 语句就会经过分析器,Mysql通过将SQL语句进行解析,并生成一棵对应的解析树。MySQL解析器将使用MySQL语法分析(语法规则验证)和解析查询,如将验证是否使用错误的关键字,或者关键字的顺序是否正确

预处理器:预处理器根据一些MySQL规则进一步检查解析树是否合法,如数据表和数据列是否存在,解析列名和别名,是否有歧义。接下来预处理器会验证用户权限(precheck)。查看用户是否有相应的操作权限

优化器: 按照 MySQL 认为最优的方案去执行。例如表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序,将SQL语句转化成执行计划,一条查询可以有很多种执行方式,最后都返回相同的结果,最后找到其中最好的执行计划(Mysql使用基于成本的优化器,它将尝试预测一个查询使用某种执行计划的成本,选择其中成本最小的一个)

执行器: Mysql根据执行计划给出的指令逐步执行。在此过程中,有大量的操作需要通过调用存储引擎实现的接口完成,这些接口即为“handler API”接口。查询中的每一个表由一个handler的实例表示。(实际上,在优化阶段Mysql就为每一个表创建了一个handelr实例,优化器可以根据这些实例的接口获取表的相关信息,如表的所有列名、索引统计信息等)

下面的一层为存储引擎,以及真实存储的数据,存储引擎又分为很多中,在【MySQL数据库基础 五】数据库存储引擎这篇文章里详细的分析过MySQL的存储引擎选择。

SQL语句执行流程

了解了MySQL的架构之后呢,正式理解下一条语句如何进行执行和优化。

查询语句

以如下的查询语句举例分析,从人员库的人员信息表里拿出一条人员数据:

use User

go

select * from UserInfo where name='tml' and age='26' and sex='男';

分析下这个语句的执行流程:

连接器: 连接数据库User,并通过输入账号密码通过连接认证

查询缓存: 先执行查询缓存,如果命中数据,在返回之前先判断是否有权限,如果有则返回,没有则继续向下

分析器: 若没有命中缓存,进行语法分析,提取关键字:use 、go、select 、from 、where 、and ,判断关键字是否满足MySQL的语法

预处理器:进一步获取UserInfo表名、列名:name、age、sex,判断这些元素是否都存在,如果都存在则验证权限,如果权限存在继续向下

优化器: 判断先获取哪一列,产生各种方案【name->age->sex、name->sex->age、age->sex->name等】,最终会选取最优、成本最小的方案去执行

执行器: 调用handler查询相关接口,从InnoDB存储引擎中获取数据

以上就是查询语句的执行流程。

DML数据操作语句

DML数据操作语句(更新、删除、插入)这些在执行的时候肯定要记录日志,MySQL 自带的日志模块 binlog(归档日志) ,所有的存储引擎都可以使用,常用的 InnoDB 引擎还自带了一个日志模块 redo log(重做日志),假如我们要更新tml的age为18:

use User

go

update UserInfo set age='18' where name='tml';

我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下:

连接器: 连接数据库User,并通过输入账号密码通过连接认证

查询缓存: 先执行查询缓存,如果命中数据,在返回之前先判断是否有权限,如果有则返回,没有则继续向下

分析器: 若没有命中缓存,进行语法分析,提取关键字:use 、go、update 、set 、where ,判断关键字是否满足MySQL的语法

预处理器:进一步获取UserInfo表名、列名:name、age,判断这些元素是否都存在,如果都存在则验证权限,如果权限存在继续向下

优化器: 定位到要更新的数据,查询tml这一条数据,然后把age改为18

执行器: 调用handler查询相关接口写入这一行数据

InnoDB 引擎把数据保存在内存中**,同时记录 redo log,此时 redo log 进入 prepare 状态**,然后告诉执行器,执行完成了,随时可以提交

执行器收到通知后记录 binlog,然后调用引擎接口,提交 redo log 为提交状态。

更新完成

以上就是在更新数据时的一些操作,实际上只比查询多后半段。

日志与事务

涉及到日志的一部分内容,日志这一部分主要用于事务和持久化,redo log和binlog的执行顺序如果不正确会导致如下问题:

先写 redo log 直接提交,然后写 binlog,假设写完 redo log 后,机器挂了,binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 bingog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。

先写 binlog,然后写 redo log,假设写完了 binlog,机器异常重启了,由于没有 redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。

如果采用 redo log 两阶段提交的方式就不一样了,写完 binglog 后,然后再提交 redo log 就会防止出现上述的问题,从而保证了数据的一致性。采用这种方式再验证一下:

写redo log 预提交过程中,机器挂了,则回滚事务

写完redo log 预提交,并且写binglog过程中 ,机器挂了,则判断

如果 redo log 完整,则立即提交

如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务

这样就解决了数据一致性的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值