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