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

2次阅读

共计 2754 个字符,预计需要花费 7 分钟才能阅读完成。

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 版本开始成为了默认存储引擎。

2.2 更新 SQL 的执行

当咱们执行一条更新 SQL 时是如何执行的呢,上面执行一条简略的 SQL 更新语句(默认存储引擎 InnoDB)
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 有没有执行查问的权限,如果没有,就会返回没有权限的谬误。执行器负责具体执行,找到这一行,而后更新。

2.3 InnoDB 存储引擎引入 REDOLOG

Mysql 自身有本人的日志记录 binlog(归档日志: 分为 row,statement 两种模式),然而只依附 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 的批改,办法如下:
(Page ID,Record Offset,(Filed 1, Value 1) … (Filed i, Value i) … )
其中,PageID 指定要操作的 Page 页,Record Offset 记录了 Record 在 Page 内的偏移地位,前面的 Field 数组,记录了须要批改的 Field 以及批改后的 Value。

2.4 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 的设计的思路和原理,为当前的利用零碎的开发和设计提供思维上的借鉴和实际。

正文完
 0