从一条更新 SQL 的执行过程窥探 InnoDB 之 REDOLOG

3A网络
• 阅读 647

从一条更新 SQL 的执行过程窥探 InnoDB 之 REDOLOG

1 前言

数据库为了取得更好的读写性能,InnoDB 会将数据缓存在内存中(InnoDB Buffer Pool),对磁盘数据的修改也会落后于内存,这时如果进程或机器崩溃,会导致内存数据丢失,为了保证数据库本身的一致性和持久性,InnoDB 维护了 REDO LOG。修改 Page 之前需要先将修改的内容记录到 REDO 中,并保证 REDO LOG 早于对应的 Page 落盘,也就是常说的 WAL,Write Ahead Log。当故障发生导致内存数据丢失后,InnoDB 会在重启时,通过重放 REDO,将 Page 恢复到崩溃前的状态。

2 MYSQL 更新语句的执行过程

2.1 MYSQL 的体系结构

大体来说,MySQL 可以分为 客户端、Server 层和存储引擎层三大部分,如图所示。

Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。

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

从一条更新 SQL 的执行过程窥探 InnoDB 之 REDOLOG

2.2 更新 SQL 的执行

当我们执行一条更新 SQL 时是如何执行的呢,下面执行一条简单的 SQL 更新语句 (默认存储引擎 InnoDB)

  1. update T set c=c+1 where ID=2;

第一步:连接器 先通过连接器连接到这个数据库上。连接器负责跟客户端建立连接、校验用户名密码的正确性,同时获取该用户的权限放到缓存中、维持和管理连接

第二步:缓存 连接建立完成后,如果执行的是 SELECT 查询 语句会查询缓存中是否存在该 SQL 的结果集,如果存在结果则再校验用户表和数据的权限最终将查询到的结果返回。如果是 UPDATE,DELETE 等更新操作,那么跟这个表有关的查询缓存会置为失效,所以这条语句就会把表 T 上所有缓存结果都清空。

第三步:分析器 如果没有命中查询缓存,就要开始真正执行语句了。首先,MySQL 需要知道你要做什么,因此需要对 SQL 语句做解析。 分析器先会做 “词法分析”。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。例如该语句中 c 列在表 T 中是否存在等。 做完了这些识别以后,就要做 “语法分析”。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。该 SQL 语句中的 update、where 等是否符合 SQL 语法

第四步:优化器 经过了分析器,MySQL 就知道你要做什么了。在开始执行之前,还要先经过优化器的处理。优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序;优化器决定要使用 ID 这个索引。指定索引也就指定了后面的执行器需要调用存储引擎的哪个接口进行执行。

第五步:执行器 MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误。执行器负责具体执行,找到这一行,然后更新。

从一条更新 SQL 的执行过程窥探 InnoDB 之 REDOLOG

2.3 InnoDB 存储引擎引入 REDOLOG

Mysql 本身有自己的日志记录 binlog (归档日志:分为 row,statement,mix 三种模式),但是只依靠 binlog 是没有 crash-safe 能力的,所以在存储引擎层 InnoDB 使用另外一套日志系统 redolog 来实现 crash-safe 能力。同时为了取得更好的读写性能,InnoDB 会将数据缓存在内存中(InnoDB Buffer Pool),对磁盘数据的修改也会落后于内存,这时如果进程或机器崩溃,会导致内存数据丢失,从而保证数据库本身的一致性和持久性。修改 Page 之前需要先将修改的内容记录到 REDO 中,并保证 REDO LOG 早于对应的 Page 落盘,也就是常说的 WAL,Write Ahead Log。当故障发生导致内存数据丢失后,InnoDB 会在重启时,通过重放 REDO,将 Page 恢复到崩溃前的状态。

那么我们需要什么样的 REDO 呢?

首先,REDO 的维护增加了一份写盘数据,同时为了保证数据正确,事务只有在他的 REDO 全部落盘才能返回用户成功,REDO 的写盘时间会直接影响系统吞吐,显而易见,REDO 的数据量要尽量少。其次,系统崩溃总是发生在始料未及的时候,当重启重放 REDO 时,系统并不知道哪些 REDO 对应的 Page 已经落盘,因此 REDO 的重放必须可重入,即 REDO 操作要保证幂等。最后,为了便于通过并发重放的方式加快重启恢复速度,REDO 应该是基于 Page 的,即一个 REDO 只涉及一个 Page 的修改。 数据量小是 Logical Logging 的优点,而幂等以及基于 Page 正是 Physical Logging 的优点。InnoDB 采取了一种称为 Physiological Logging 的方式,来兼得二者的优势。所谓 Physiological Logging,就是以 Page 为单位,但在 Page 内以逻辑的方式记录。举个例子,一种作用于 Page 类型的 REDOLOG 中记录了对 Page 中一个 Record 的修改,方法如下:

  1. (Page ID,Record Offset,(Filed 1, Value 1) … (Filed i, Value i) … )

其中,PageID 指定要操作的 Page 页,Record Offset 记录了 Record 在 Page 内的偏移位置,后面的 Field 数组,记录了需要修改的 Field 以及修改后的 Value。

2.4 REDOLOG 的记录内容

从一条更新 SQL 的执行过程窥探 InnoDB 之 REDOLOG

其中 Type 就是记录的作用对象 (根据 REDO 记录不同的作用对象,可划分为三个大类:作用于 Page,作用于 Space 以及提供额外信息的 Logic 类型),Space ID 和 Page Number 唯一标识一个 Page 页,这三项是所有 REDO 记录都需要有的头信息。

后面的是 MLOG_REC_UPDATE_IN_PLACE 类型 (作用于 Page) 独有的,其中 Record Offset 用给出要修改的记录在 Page 中的位置偏移,Update Field Count 说明记录里有几个 Field 要修改,紧接着对每个 Field 给出了 Field 编号 (Field Number),数据长度(Field Data Length)以及数据(Filed Data)

3 总结

通过对一个更新 SQl 语句执行过程的跟踪,了解熟悉 Mysql 的执行过程,了解 REDOLOG 的数据的内容格式,从根本上理解 REDOLOG 的设计的思路和原理,为以后的应用系统的开发和设计提供思想上的借鉴和实践,感兴趣的可以在3A的服务器上部署一套自己尝试练习一下。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
2年前
InnoDB存储引擎
InnoDB存储引擎InnodbBufferPool(缓存池)InnodbBufferPool的概念InnoDB的BufferPool主要用于缓存用户表和索引数据的数据页面。它是一块连续的内存,通过一定的算法对这块缓存做有效的管理。官方文档建议,如果此台服务器为MySQL专用数据库服务
Wesley13 Wesley13
2年前
MySQL 日志(redo log 和 undo log) 都是什么鬼东西!?
innodb事务日志包括redolog和undolog。redolog是重做日志,提供前滚操作,undolog是回滚日志,提供回滚操作。undolog不是redolog的逆向过程,其实它们都算是用来恢复的日志:1.redolog通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数
Wesley13 Wesley13
2年前
MySQL数据库InnoDB存储引擎Log漫游(1)
作者:宋利兵来源:MySQL代码研究(mysqlcode)0、导读本文介绍了InnoDB引擎如何利用UndoLog和RedoLog来保证事务的原子性、持久性原理,以及InnoDB引擎实现UndoLog和RedoLog的基本思路。00–UndoLogUndoLog是为了实现事务的原子性,
Stella981 Stella981
2年前
InnoDB脏页刷新机制Checkpoint
我们知道InnoDB采用WriteAheadLog策略来防止宕机数据丢失,即事务提交时,先写重做日志,再修改内存数据页,这样就产生了脏页。既然有重做日志保证数据持久性,查询时也可以直接从缓冲池页中取数据,那为什么还要刷新脏页到磁盘呢?如果重做日志可以无限增大,同时缓冲池足够大,能够缓存所有数据,那么是不需要将缓冲池中的脏页刷新到磁盘。但是,通常会有以下几
Wesley13 Wesley13
2年前
MySQL InnoDB如何保证事务特性
如果有人问你“数据库事务有哪些特性”?你可能会很快回答出原子性、一致性、隔离性、持久性即ACID特性。那么你知道InnoDB如何保证这些事务特性的吗?如果知道的话这篇文章就可以直接跳过不看啦(^.^)先说结论:redolog重做日志用来保证事务的持久性undolog回滚日志保证事务的原子性undologredo
Wesley13 Wesley13
2年前
MySQL数据库InnoDB存储引擎Log漫游(3)
作者:宋利兵来源:MySQL代码研究(mysqlcode)0、导读本文重点介绍了InnoDB的checkpoint和BufferPool管理04–Checkpoint理论上来说,如果MySQL数据库InnoDB存储引擎的buffer足够大,就不需要将数据本身持久化。将全部的redolog重新执行
Stella981 Stella981
2年前
Innodb Buffer Pool的三种Page和链表
一、InnodbBufferPool简介BufferPool是Innodb内存中的的一块占比较大的区域,用来缓存表和索引数据。众所周知,从内存访问会比从磁盘访问快很多。为了提高数据的读取速度,BufferPool会通过三种Page和链表来管理这些经常访问的数据,保证热数据不被置
Stella981 Stella981
2年前
Memcached 缓存数据库应用实践
1.1数据库对比缓存:将数据存储到内存中,只有当磁盘胜任不了的时候,才会启用缓存  缺点:断电数据丢失(双电),用缓存存储数据的目的只是为了应付大并发的业务。数据库:mysql(关系型数据库,能够保证数据一致性,保证数据不丢失,当因为功能太多,导致性能不高)数据参考缓存数据库:me
Mysql的undo log、redo log、binlog和MVCC
本文试图解释undolog,redolog,binlog的作用,以及Innodb的MVCC机制undologundolog记录的是sql语句执行更新前的数据,这里的更新是泛指,除了select其它都算更新。在读已提交和可重复读的隔离级别下,会记录事务中某条