Mysql的执行过程详解

338 阅读4分钟

执行过程

image.png

假设写一条

SELECT stuName,age,sex FROM students WHERE id=1

1. 查询解析器

经过查询解析器,就可以传过来的sql语句进行解析,翻译成mysql知道的语言。

2.查询优化器

接下来,Mysql的查询优化器会使用他认为最好的方式的优化这一条sql语句,并生成许多条执行计划,然后执行成本最小的执行计划。

优化器执行选出最优索引等步骤后,会去调用存储引擎接口,开始去执行被  MySQL  解析过和优化过的 SQL 语句

3.执行器

执行器最终最根据一系列的执行计划去调用存储引擎的接口去完成  SQL  的执行

4.存储引擎

查询优化器通过执行器去调用存储引擎的接口,去执行  SQL。真正执行sql的动作是在存储引擎中完成的。

下面就对Mysql的存储引擎做一个介绍

UPDATE students SET stuName = '小强' WHERE id = 1

当我们写一个sql语句交给Mysql时,所需要的数据可能在内存里,也可能在磁盘上。如果每次到在磁盘上进行操作,那么IO时间太长,肯定是无法接受的,所以每次执行Sql的时候都会将数据加载到内存中,这块内存就是InnoDB中的:缓冲池 Buffer Pool

4.1 Buffer Pool

Mysql中的数据最终都会持久化到磁盘上,如果每次操作都要经过磁盘,那IO的时间是无法接受的。但是有了Buffer Pool,第一次sql查询的数据会将结果放到Buffer Pool中,后面再有查询请求就会先去Buffer Pool中去查找,如果没有的话,就去磁盘中找,然后再放到Buffer Pool中

4.2 undo日志文件

Undo 顾名思义就是 没有做 的意思。 undo log 就是记录数据被修改前的样子。

之前的update语句,当它被加载到Buffer Pool中时,同时也会向undo log 中插入一条日志,也就是把id = 1 的未修改之前的数据保存一份。

为什么要这样做呢?

因为InnoDB是支持事务的。如果本次更新失败了,也就是事务提交失败了,那么该事务中的所有操作都必须回滚到执行前的样子。那么即使事务失败了,也不会对原始数据有任何影响。

这条update语句被加载在Buffer Pool中执行,此时,缓存中的数据被修改成了「小强」,而数据库中的不一定是「小强」,这就造成了缓存和数据库中的数据不一致了。那么Mysql会怎么来处理呢?

4.3 redo 日志文件

除了从磁盘中加载的文件和操作之前的文件会保存到undo日志文件中, 其他操作都是在内存中完成的,内存的特点是:断电丢失。如果在进行数据库操作时,某人把电源拔了,那么Buffer Pool 中的数据就全没了。这肯定是不行的,所有redo日志文件孕育而生。

redo 日志文件是 InnoDB 特有的,他是存储引擎级别的,不是 MySQL 级别的

redo记录的是数据修改之后的值,不管事务是否提交都会记录下来。

比如某一条sql语句的记录,会先记录到redo log buffer中(在内存中完成),将来某个时机会持久到磁盘中。

4.4 bin log 日志文件

之前提到的redo log 是InnoDB特有的,偏向于物理性质

bin log 是Mysql级别的日志,偏向于逻辑性质

两者的特点区别如下:

bin log 是怎么记录日志的呢?

在mysql提交事务的时候,不仅仅会将redo log buffer 中的数据写入redo log 文件中,同时也会将本次修改的数据记录到bin log文件中,同时会将本次修改的bin log 文件名和修改的内容在 bin log 中的位置记录到redo log 中,最后还会在redo log 最后写入commit标记,这样就表示本次事务成功提交了。

总结

mysql的执行器调用存储引擎是怎么将一条sql加载到缓冲池和记录到哪些日志的?流程如下:

  1. 准备更新一条sql语句
  2. Innodb会先去缓冲池(Buffer Pool)中去查找这条数据,没找到就去磁盘中找,找到后再把该数据加载到Buffer Pool
  1. 在加载到Buffer Pool的同时,会把这条数据的原始记录保存到undo日志文件中
  2. innodb会在Buffer Pool中执行更新操作。
  1. 更新后的数据会记录到redo log buffer中。
  2. 完成后就可以提交事务了,这时会做三件事
  1. ①将redo log buffer中的数据刷入到 redo log 文件中
  2. ②将本次操作记录写入到 bin log文件中
  1. ③将 bin log 文件名字和更新内容在 bin log 中的位置记录到redo log中,同时在 redo log 最后添加 commit 标记