likes
comments
collection
share

(四)MySQL日志篇-1:一条sql语句是如何执行的?

作者站长头像
站长
· 阅读数 5

一条普通的sql语句是如何执行的?

MySQL的内部架构及作用

今天开始是我们日志篇的内容啦,在正式开盘日志之前,需要先做个前提概要,就是搞明白一件事:MySQL是如何执行一条sql语句的。而弄清楚这个问题,就需要我们先理清楚MySQL的基础架构

基本的架构如下图, 下面以执行一条普通的select语句为例,盘一下每个组件的具体作用

(四)MySQL日志篇-1:一条sql语句是如何执行的?

从整体来说,MySQL可分为Server层和引擎层

Server层包括连接器,分析器,优化器,执行器,包含了MySQL大部分的功能。例如:所有的计算(函数,日期,时间等),存储过程,视图等。

引擎层负责数据的存和取,模式是插件式(可插拔,替换),有InnoDB, MyISAM等常见引擎。其中InnoDB为MySQL5.7版本后的默认引擎

连接器

连接器主要负责管理连接,权限验证

无论是通过命令行窗口,Navicat,还是企业项目使用MySQL,第一步肯定是要和MySQL建立TCP连接,而这些连接工具对于MySQL来说都是客户端。连接的第一件事就是要在连接器这里做身份验证,如下:

                            mysql -h$host -P$port -u$user -p$pwd

如果密码错误,将会被拒绝连接;如果密码正确,连接器将会判断并保存登录的用户拥有的权限,之后执行任何操作(DML,DDL等)都会根据最初登录所获得的权限来做校验

登录成功后,通过 show processlist; 可看到当前客户端的连接数量

(四)MySQL日志篇-1:一条sql语句是如何执行的?

我在本地开启了两个客户端,如果连接建立后没做什么操作的话,连接就会变成Sleep(空闲)。如果太长时间没有动静的话,连接器就会主动将客户端关闭,由如下参数控制(默认是8小时):

(四)MySQL日志篇-1:一条sql语句是如何执行的?

查询缓存

缓存的作用是提升查询效率

当一条select语句进来时,会先去判断下是否有相关缓存,如果有的话,直接返回;没有的话才会去走分析器那一步。

但本质上这个功能很鸡肋,在MySQL5.7及之后的版本就已经被移除了,原因如下:

  1. 如果碰到update语句,需要不断更新缓存值,在读少写多的情况下效率更差
  2. 缓存是以K-V形式存储,key是查询的sql,而value是值。 只要select后面的字段随便变一下,缓存就无法命中

因此在大多数情况下,MySQL的缓存功能是弊大于利的, 因此后面也被移除掉了

分析器

分析器的主要作用:语义,语法分析

这时候才要开始真正执行的sql了,先交给分析器处理,让MySQL知道你想要做什么? 因此需要对sql进行预处理。比方说:

  1. 如果是select *,解析具体要查询的列,将 *替换成具体的列ID
  2. 识别这条sql需要访问的表,是否规范,存在等;
  3. 判断筛选的条件的列是否存在,符合规范(若有)等;

以及看这条sql是否符合MySQL的语法规范,有没有乱写。如下的例子:

(四)MySQL日志篇-1:一条sql语句是如何执行的?

前两条sql都是被分析器检测出查询的表、筛选的字段不存在被拦截

后一条sql则是不符合MySQL的语法规范,提示大家初学必会出现的经典的You hava an error ...

优化器

优化器的主要作用:生成这条sql具体的执行计划,优化方案

讲过了分析器,那MySQL就明白你要做什么了,下一步就要开始制定执行计划。就类似做产品一样,一开始总是要知道做它的目的(为什么要做),紧接着针对这个产品开始制定一系列的方针和计划。而sql就是我们的“产品”

优化器处理完后,sql具体的执行方案就定下来了,进入下一阶段!

执行器

执行器的主要作用:去操作引擎拿数据,并带回数据

优化器告诉了MySQL要做什么分析器告诉了要怎么去做,这时候就需要有一个执行者来行动了。

这时候,执行器的操作顺序大致如下:

  1. 打开要操作的表,去根据这个表用到的是哪个引擎,去调引擎提供的相应接口
  2. 根据执行计划,没有索引的话,就调接口一行数据一行数据取,然后再判断是否符合条件
  3. 如果有索引的话,就通过查字典的方式精准定位,将结果放入结果集

最后,将符合条件的结果集再打包处理,返回给客户端,这条sql就处理完成了!

日志在MySQL中起到什么作用?

对于查询操作来说,查询总是幂等的(如果没有增删改操作,执行多少次查询结果都是一样的)。因此,我们也不必去考虑查询时,碰到的各种突发情况(断电,宕机,并发等等),会影响到数据的一致性。对于增,删,改操作就不一样了!

执行增删改的sql,肯定也是要走 连接器->分析器->优化器->执行器 的流程。除此之外,还需要做一些安全性措施(防止出现什么意外情况,数据不会丢失,错乱)。这时候,我们的日志就要登场啦!执行一条增删改语句时,还会同时写几个日志!(MySQL三大日志,binlog;redo log;undo log悉数登场

binlog是干什么用的?

binlog的主要作用是:主从复制,归档备份

写的时机:当MySQL执行完一条增删改sql后,执行器会将该sql写到binlog中。

使用MySQL肯定不会对主从复制感到陌生。而从库的数据从哪里来呢?

当主库执行增删改语句时,会将语句“写”在binlog日志里面,然后将binlog同步到从库上,从库直接执行就完事了!

undo log是干什么用的?

undo log的主要作用体现在两个地方,1:MVCC;2:事务的原子性

写的时机:当MySQL执行完一条增删改sql时,执行器会调用innoDB引擎的接口将sql的反义写到undo log中。(一条insert对应delete;一条delete对应insert;一条update new 对应update old;便于回滚)

  1. MySQL的快照读是通过MVCC来解决事务的并发问题的,那历史版本记录放在哪里呢?就放在undo log里面

  2. 事务的原子性保证一个事务内的所有操作要么都成功,要么都失败。如果成功一半,失败了,就要通过undo log日志来回滚

redo log是干什么用的?

redo log的主要作用:保证数据不丢失,具备crash-safe能力(InnoDB引擎独有)

写的时机:当MySQL执行完一条增删改sql时,**执行器会调用innoDB引擎的接口将sql写到redo log中。

如果因为突发情况而导致丢数据,那这是很危险的事情了。redo log的存在即保证了数据的不丢失,具体的原理我们会在稍后展开。

如果将redo log, undo log, binlog都结合到MySQL的架构,则执行一条增删改语句时,执行流程如下图:

(四)MySQL日志篇-1:一条sql语句是如何执行的?


未完待续~~~ 后面会详细剖析每种日志的作用!

转载自:https://juejin.cn/post/7317465809819353097
评论
请登录