2. Sql执行过程

  1. Mysql架构 https://blog.csdn.net/qq_34177163/article/details/129317460

  1. sql执行过程 https://blog.csdn.net/qq_34177163/article/details/129320728

  1. InnoDB总体架构解析 https://blog.csdn.net/qq_34177163/article/details/129355991

  1. B+树详细解析 https://blog.csdn.net/qq_34177163/article/details/129356044

题记

了解了Mysql的架构之后,里面大多是查询的一条路线,那么更新,删除,写入流程也是如此吗,让我们带着问题一探究竟。

1. 存储引擎

我们以一个更新的SQL语句来说明,SQL 如下

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

当我们系统发出这样的查询去交给 MySQL 的时候,如果直接在磁盘中操作,那这样的随机IO读写的速度肯定让人无法接受的。Mysql每次在执行 SQL 的时候都会将其数据加载到内存中,这块内存就是下边要介绍的Buffer Poll。

2.Buffer Pool

InnoDB设计了一个内存的缓冲区。读取数据的时候,先判断是不是在这个内存区域里面,如果是,就直接读取,然后操作,不用再次从磁盘加载。如果不是,读取后就写到这个内存的缓冲区中即放入buffer pool中。如下图

2. Sql执行过程_第1张图片

此时sql的执行步骤为:

  • innodb 存储引擎会在缓冲池(buffer pool)中查找 id=1 的这条数据是否存在

  • 发现不存在,那么就会去磁盘中加载,并将其存放在缓冲池中

  • 该条记录会被加上一个独占锁(避免在此次事务中修改时别的事务再进行其他操作)

好,第一步基础我们完成,再看下边的流程

3.undo 日志文件

说明:记录数据被修改前的样子,可以理解为记录此次事务的方向操作,比如insert语句记录的是delete,update会记录update原来的数据。如下图

2. Sql执行过程_第2张图片

此时上边的那条sql执行流程就变成了

  1. innodb 存储引擎会在缓冲池(buffer pool)中查找 id=1 的这条数据是否存在。

  1. 发现不存在,那么就会去磁盘中加载,并将其存放在缓冲池中。

  1. 在放入缓冲池时候同时将数据写入到undo log 文件中。

这样做的目的是什么

Innodb 存储引擎的最大特点就是支持事务,如果本次更新失败,也就是事务提交失败,那么该事务中的所有的操作都必须回滚到执行前的样子,怎么进行处理呢,此时undo log就起到了至关重要的作用。

查看undolog日志配置命令

show global variables like "%undo%";
2. Sql执行过程_第3张图片
2. Sql执行过程_第4张图片

此时,我们理解了在写入buffer pool时的undolog流程。

4.redo 日志文件

说明:记录数据被修改后的样子。即此次要进行的事务操作。

修改数据的时候,是先写入到 buffer pool,而不是直接写到磁盘。内存的数据页和磁盘数据不一致的时候,我们把它叫做脏页。那脏页什么时候才同步到磁盘呢?InnoDB里面有专门的后台线程把 Buffer Pool的数据写入到磁盘,每隔一段时间就一次性地把多个修改写入磁盘,这个动作就叫做刷脏。

问题:

因为刷脏不是实时的,如果 Buffer Pool里面的脏页还没有刷入磁盘数据库宕机或者重启,这些数据就会丢失。

为了避免这个问题,InnoDB把所有对页面的修改操作专门写入一个日志文件(redolog)如果有未同步到磁盘的数据,数据库在启动的时候,会从这个日志文件进行恢复操作(实现 crash-safe)。我们说的事务的ACID 里面 D(持久性),就是用它来实现的。如下图

2. Sql执行过程_第5张图片

至此流程如下:

  1. innodb 存储引擎会在缓冲池(buffer pool)中查找 id=1 的这条数据是否存在。

  1. 发现不存在,那么就会去磁盘中加载,并将其存放在缓冲池中。

  1. 在放入缓冲池时候同时将数据写入到undo log 文件中。

  1. innodb 会在 Buffer Pool 中执行更新操作

  1. 更新后的数据会记录在 redo log buffer 中

这个redo log 有什么特点?

  1. redolog是lnnoDB 存储引擎实现的,并不是所有存储引擎都有。支持崩溃恢复是InnoDB的一个特性。

  1. redolog不是记录数据页更新之后的状态,而是记录的是“在某个数据页上做了什么修改”。属于物理日志。

  1. redolog的大小是固定的,前面的内容会被覆盖,一旦写满,就会触发 buffer pool到磁盘的同步,以便腾出空间记录后面的修改

  1. redo 日志文件中 刷磁盘可以通过 innodb_flush_log_at_trx_commit 参数来设置

值为 0 表示不刷入磁盘

值为 1 表示立即刷入磁盘

值为 2 表示先刷到 os cache

  1. myslq 重启的时候会将 redo 日志恢复到缓冲池中

redolog,undolog 统称为事务日志

下边就是重中之重了,再坚持一下。毕竟事务还没有提价呢。

5.bin log 日志文件

说明:记录整个操作过程

上面介绍到的redo log是 InnoDB 存储引擎特有的日志文件,而bin log属于是 MySQL 级别的日志。redo log记录的东西是偏向于物理性质的,如:“对什么数据,做了什么修改”。bin log是偏向于逻辑性质的,类似于:“对 students 表中的 id 为 1 的记录做了更新操作” 两者的主要特点总结如下:

性质

redo Log

bin Log

文件大小

redo log 的大小是固定的(配置中也可以设置,一般默认的就足够了)

bin log 可通过配置参数max_bin log_size设置每个bin log文件的大小(但是一般不建议修改)。

实现方式

redo log是InnoDB引擎层实现的(也就是说是 Innodb 存储引擎独有的)

bin log是 MySQL 层实现的,所有引擎都可以使用 bin log日志

记录方式

redo log 采用循环写的方式记录,当写到结尾时,会回到开头循环写日志。

bin log 通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上

使用场景

redo log适用于崩溃恢复(crash-safe)(这一点其实非常类似与 Redis 的持久化特征)

bin log 适用于主从复制和数据恢复

bin log文件是如何刷入磁盘的?

bin log 的刷盘是有相关的策略的,策略可以通过sync_binlog来修改。

2. Sql执行过程_第6张图片

0:表示先写入 os cache,也就是说在提交事务的时候,数据不会直接到磁盘中,这样如果宕机bin log数据仍然会丢失。

1: 表示直接将数据写入到磁盘文件中。

流程如下图:

2. Sql执行过程_第7张图片

此时的流程为:

  1. innodb 存储引擎会在缓冲池(buffer pool)中查找 id=1 的这条数据是否存在。

  1. 发现不存在,那么就会去磁盘中加载,并将其存放在缓冲池中。

  1. 在放入缓冲池时候同时将数据写入到undo log 文件中。

  1. innodb 会在 Buffer Pool 中执行更新操作

  1. 更新后的数据会记录在 redo log buffer 中。

  1. 同时会将本次修改的数据记录到 bin log文件中。

  1. 将本次修改的bin log文件名和修改的内容在bin log中的位置记录到redo log中。

  1. 最后还会在redo log最后写入 commit 标记,这样就表示本次事务被成功的提交了。

6. 数据保持统一

如果在数据被写入到bin log文件的时候,刚写完,数据库宕机了,数据会丢失吗?

肯定不能丢失的, 只要redo log最后没有 commit 标记,说明本次的事务一定是失败的。但是数据是没有丢失了,因为已经被记录到redo log的磁盘文件中了。在 MySQL 重启的时候,就会将 redo log 中的数据恢复(加载)到Buffer Pool中。然后就又可以快乐玩耍了。

另外,Mysql还有一个后台线程会维护buffer pool和磁盘数据一致。如下图:

2. Sql执行过程_第8张图片

至此:一个完整的执行流程我们了解完了,最后我们再总结一下。

7. 总结

  1. innodb 存储引擎会在缓冲池(buffer pool)中查找 id=1 的这条数据是否存在。

  1. 发现不存在,那么就会去磁盘中加载,并将其存放在缓冲池中。

  1. 在放入缓冲池时候同时将数据写入到undo log 文件中。

  1. innodb 会在 Buffer Pool 中执行更新操作

  1. 更新后的数据会记录在 redo log buffer 中。

  1. 同时会将本次修改的数据记录到 bin log文件中。

  1. 将本次修改的bin log文件名和修改的内容在bin log中的位置记录到redo log中。

  1. 最后还会在redo log最后写入 commit 标记,这样就表示本次事务被成功的提交了。

  1. 后台会有线程对buffer pool与磁盘数据进行刷脏处理保持数据一致性。

你可能感兴趣的:(Mysql,mysql)