MySQL实战45讲 1sql的执行过程 2日志系统

1.sql的执行过程

MySQL的基本逻辑架构

img

Service层(客户端层)大多的跨引擎的功能都在这里,如存储过程。不同的存储引擎共用一个service层。

存储引擎层负责数据的提取和存储。其架构是插件时的,即持 InnoDB、MyISAM、Memory 等多个存储引擎。InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。

每个组件的作用

连接器

当连接上数据库时,会先于连接器交互。它负责跟客户端建立连接,校验密码,获取权限,管理连接等。

数据库里长链接指连接成功后,如果后续有多次请求,则用的是同一个连接。短连接是执行少量的查询便断开。下次查询再重新建立一个。

尽量减少使用长链接。mysql执行中一些数据绑定在连接对象中,因为长连接长时间不断开导致内存占用太多。可以使用定时超时断开,或通过重新初始化链接来清空。

查询缓存

建立连接后。则开始查询缓存。MySQL拿到请求后,会先去查询缓存,是否有相关数据。之前执行的语句及其结果会以key-value的形式,被缓存在内存中。key是查询语句,value是结果。若有,则返回value,若没有,则执行后续的操作,并将结果插入缓存。

但查询缓存命中率太低。因为只要对表有更新,就会让整个表的缓存清空。建议静态表使用。

可以将参数 query_cache_type 设置成 DEMAND,这样对于默认的 SQL 语句都不使用查询缓存。而对于你确定要使用查询缓存的语句,可以用 SQL_CACHE 显式指定,像下面这个语句一样:

1
csharp复制代码mysql> select SQL_CACHE * from T where ID=10;

MySQL 8.0 版本直接将查询缓存的整块功能删掉了

分析器

若没有命中缓存,则开始执行语句。首先分析器会做词法分析,它要知道语句中的单词都是什么意思。如识别关键字,表名,列名等。

然后再进行语法分析,分析sql是否满足语法。

优化器

分析器让MySQL明白你要干什么,优化器则要开始决定怎么做。每个语句不同的执行顺序带来的执行效率是不同的,如有的条件字段有索引等。优化器将会选择一个最优的方案。原则就是:尽可能少的扫描数据库行记录

执行器

通过优化器知道该怎么做,则现在要通过执行器来执行sql语句。

开始执行之前会判断一下你对要操作的表是否有相应的执行权限。到了执行的时候才会进入到数据库引擎,然后执行器也是通过调用数据库引擎的API来进行数据操作的。也因此数据库引擎才会是插件形式的。

1
csharp复制代码select * from T where ID=10;

以上语句为例,字段id没有。其过程如下:

1.调用引擎接口取表的第一行,判断id是否等于10,不是则跳过,是则存在结果集中。

2.调用接口取下一行,重复判断逻辑。直到取到表的最后一行

3.执行器将所有满足条件的行记录组成的结果集返回。

有索引跟上述过程也差不多。其中接口都是引擎定义好的。

2.日志系统

redo log(innoDB特有)

redolog是物理日志,记录的是“在某个数据页做了什么修改”。

当有一条记录更新时,InnoDB引擎先把记录写到redo log 中,redo log 也在磁盘上,这也是一个写磁盘的过程,但是与更新过程不一样的是,更新过程是在磁盘上随机IO,费时。 而写redo log 是在磁盘上顺序IO。效率要高。

同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。

与此类似,InnoDB 的 redo log 是固定大小的,是循环写。比如可以配置为一组 4 个文件,每个文件的大小是 1GB。从头开始写,写到末尾就又回到开头循环写,如下面这个图所示。

img

write pos是当前记录的位置,一边写一遍往后推。check point是当前要擦除的位置,也是往后推且循环。当两个点重合,表示redo long满了,将不会执行新的更新操作,擦掉一下记录,并将check point往后推。

擦除记录之前,会将要擦除的记录给写入磁盘中。

redo log保证了在宕机,发生异常时时候保证之前更新的数据不会丢失。这个能力成为carsh-safe

binlog(service层特有,与存储引擎无关)

binlog是逻辑日志,记录是语句的原始逻辑,如“给id为1的a字段加1”

binlog是追加写,是指当binlog文件写到一定的大小时,会换一个文件继续写,不会删除、覆盖之前的记录。

两阶段提交

当执行更新操作时。两日志的流程如下:

1.将更新后的数据更新到内存中,同时将这次的更新操作写入redo log中,此时redo log处于prepare状态。并告知执行器执行完成,并可以随时提交事务。

2.执行器生成这个操作的binlog,并把binlog写入磁盘。

3.执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。

img

\

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%