InnoDB 存储引擎<六> Redo log

目录

关于Redo Log 的一些其余问题

小结


本篇承接自InnoDB存储引擎<五>的内容

InnoDB 存储引擎<五>

关于Redo Log 的一些其余问题

4.不同⽇志类型对应了哪些操作?

分析过程:
1.⽇志类型总体可以分为三⼤类,分别是:⽤于数据⻚的⽇志类型、⽤于表空间⽂件的⽇志类型和提供额外信息的⽇志类型,不同的⽇志类型对应的⽇志内容也不尽相同,⽽进⾏DML操作时,⼤多数RedoLog属于⽤于数据⻚的⽇志类型
2.属于⽤于数据⻚的⽇志类型中的⼏种最常⻅数据操作所对应的⽇志类型如下:
(1)MLOG_WRITE_STRING = 30 type 对应的值为30,表⽰在⻚⾯的某个偏移量处写⼊⼀个字符串,由于字符串的⻓度不固定,需要⽤到⼀个表⽰⻓度的区域记录,此时⽇志内容格式 .如下图所⽰:

(2)MLOG_4BYTES = 4, type 对应的值为4, 这种类型应⽤于对固定⻓度值的修改,⽐如修

改整型字段,由于⻓度固定,所以⽤于表⽰⻓度的区域可以省略,从⽽尽可能的减少空间使
⽤,此时⽇志内容格式如下图所⽰:

(3)类似的类型还有 MLOG_1BYTE = 1 , MLOG_2BYTES = 2 , MLOG_8BYTES = 8 分别表
⽰固定修改1字节、2字节、8字节的数据,⽇志格式与 MLOG_4BYTES = 4 相同
 (4)还有其他⼀些⽇志类型,⽐如:
      MLOG_REC_INSERT_8027 = 9 ,表⽰写⼊⼀条⾏格式为⾮紧凑型的记录,对应的⾏格
      式为Redundant
      MLOG_COMP_REC_INSERT_8027 = 38 ,表⽰写⼊⼀条⾏格式为紧凑型的记录,对应
      的格式为Compact、Dynamic和Compressed
      MLOG_REC_UPDATE_IN_PLACE_8027 = 13 ,表⽰更新⼀条记录
      MLOG_REC_DELETE_8027 = 14 ,表⽰从数据⻚中删除⼀条记录
      MLOG_LIST_END_DELETE_8027 = 15 ,表⽰从索引⻚中删除最后⼀条记录
      MLOG_LIST_START_DELETE_8027 = 16 ,表⽰从索引⻚中删除第⼀条记录
      MLOG_LIST_END_DELETE_8027 MLOG_LIST_START_DELETE_8027 配合可以删
      除索引⻚中⼀个范围的记录,⽽不⽤记录每⼀条记录的删除⽇志
      MLOG_PAGE_CREATE = 19 ,表⽰创建⼀个索引⻚,这个类型是关于⻚的类型
3. 属于⽤于表空间⽂件的⽇志类型:
     MLOG_FILE_CREATE = 33 ,表⽰创建⼀个.ibd表空间⽂件
    MLOG_FILE_RENAME = 34 ,表⽰重命名⼀个表空间⽂件
     MLOG_FILE_DELETE = 35 ,表⽰删除⼀个表空间⽂件
4.属于提供额外信息的⽇志类型:
MLOG_MULTI_REC_END = 31 ,只由⼀个字节的 Type 构成,⽤于标识⼀个 Mini-
Transaction(MTR)的结尾。
解答问题
不同的⽇志类型对应的⽇志内容和作⽤各不相同
1.⽤于数据⻚的⽇志类型
主要记录数据⻚的修改,⽐如创建和删除数据⻚,以及对数据的增删改查操作
2.⽤于表空间⽂件的⽇志类型 :主要记录对表空间⽂件的修改
3.提供额外信息的⽇志类型:主要标记⼀个Mini-Transaction的结尾
衍⽣问题
如果⼀个DML操作修改了表中的多个字段,⽇志如何表⽰?
通常情况下,⼀个DML操作会修改表中的多个字段,也可能修改多条记录,对于正常的增删改对应不同的⽇志类型,对应⽇志所包含的主要信息如下图所⽰:

1.新增操作:主要包含数据⻚内的偏移量,主键信息,新增的字段个数,每个字段的内容的实际⻓度,具体的内容等
2.删除操作:主要包含数据⻚内的偏移量,主键信息、旧事务的Id,旧roll_pointer,是否删除标识
3.更新操作:主要包含数据⻚内的偏移量,主键信息、旧事务的Id,旧roll_pointer,被更新字段的数据,每个被更新字段的实际⻓度,更新的具体内容
小结:
Redo Log的作⽤是把事务在执⾏过程中对数据库所做的所有修改都记录下来,以便在系统崩
溃重启后可以把事务所做的修改都恢复出来

5.什么是Mini-Transaction?

分析过程:

1.DML操作会对数据⻚产⽣什么样的影响? 

以⼀个Insert操作为例,对数据⻚的影响⼀般分为两种情况:
(1)如果写⼊记录所在的数据⻚空间充⾜,⾜够存储⼀条将要写⼊的记录,那么就可以直接写⼊,如下图所⽰:

(2)如果写⼊的数据⻚空间不充⾜,⽆法放下这条记录,由于在数据⻚中真实数据是按主键顺序排列的,那么就要新建⼀个数据⻚,对原来的数据进⾏调整,把⼀部分数据复制到新的数据⻚中,以便在⽬标数据⻚上留出⾜够的空间来保存即将写⼊的记录,此时对应的⽰意图如下所⽰:

(3)通过以上两种情况下插⼊⼀条记录的分析可以看出,当数据⻚空间充⾜的情况下可以直接写⼊数据,并记录⼀条对应RedoLog即可
(4)当数据⻚空间不充⾜⽆法放下这条记录的情况下,会创建⼀个新数据⻚,同时还有数据的复制和写⼊,索引树⾮叶⼦节点上修改,在实际的执⾏过程中还有对表空间中段、区中统计信息的修改等等,这意味⼀个简单的Insert操作有会产⽣很多条RedoLog。
2. 在记录RedoLog时服务器崩溃了导致⽇志不完整怎么办?
那么这时有⼀个问题需要考虑,试想⼀下如果执⾏这⼀系统操作的时候,RedoLog只记录了⼀半服务器就崩溃了,那么当服务器重启的时候如果按照RedoLog进⾏恢复,得到的结果肯定是错误的,所以在记录RedoLog的时候要保证⼀个DML所对应的⼀系列⽇志必须是完整的才可以执⾏恢复操作,否则就不执⾏恢复,那么怎么才能标记DML操作对应的日志是完整的?
3. Mini-Transaction的定义
(1)Mini-Transaction就是针对以上的操作过程定义的概念,也就是说把记录⼀个DML操作的过程称为⼀个 Mini-Transaction ,简称 MTR ⼀个所谓的MTR包含⼀个DML操作产⽣的⼀组完整⽇志,在进⾏崩溃恢复时这⼀组RedoLog做为⼀个不可分割的整体
 (2)这⾥所说的不可分割的组是MySQL中定义的,常⻅的有:
        向聚簇索引对应B+树的⻚⾯中插⼊⼀条记录时产⽣的RedoLog不可分割;
        向某个⼆级索引对应B+树的⻚⾯中插⼊⼀条记录时产⽣的RedoLog不可分割;
        还有其他的⼀些对⻚⾯的访问操作时产⽣的RedoLog不可分割。
(3)每条语句根据具体的执⾏情况可能会产⽣多个MTR。(范围更新或删除,一个事务可以包含多个MTR)
解答问题
Mini-Transaction是MySQL内部对底层数据⻚的⼀个原⼦操作,包含⼀个DML操作产⽣的⼀组完整⽇志,保证数据库异常恢复时数据⻚中数据的⼀致性
衍⽣问题
1.如何标识⼀组RedoLog属于同⼀个MTR?
在执⾏DML操作的过程中,每⼀个对数据⻚的修改都会记录⼀条RedoLog,这些⽇志会被顺序记录下来,并在这组⽇志的最后加⼀条特殊的⽇志标识作为⼀个MRT的结尾,这条特殊的⽇志结构⾮常简单,只有⼀个 TYPE 字段,类型为 MLOG_MULTI_REC_END = 31 ,也就是⽇志分类中的提供额外信息的⽇志类型,⼀个MTR对应的⽇志组,如下图所⽰:

2.如果⼀个MTR中只有⼀条⽇志是否可以优化?

(1)当然可以,如果⼀个MTR只有⼀条⽇志,直接在这条⽇志后加⼀个类型为
MLOG_MULTI_REC_END = 31 的标识可以做为MTR的结尾,但这样做有点浪费空间;
(2)InnoDB为了尽可能的节省空间,在MTR只有⼀条⽇志的情况下,做了⼀个优化。通过上⾯的介绍了解了⽇志类型虽然很多,但也只有⼏⼗种,⽽⽤来表⽰⽇志类型的 TYPE 字段⻓度为 1BTYE ,⽽这 1BTYE 中只⽤7个⽐特位,代表整数127,就完全可以表⽰所有的⽇志类型,于是省出来⼀个⽐特位就可以⽤来表⽰当前MTR包含⼀条还是⼀组RedoLog,也就是说如果 TYPE 字段的第⼀个⽐特位为 1 ,表⽰MTR只包含⼀条RedoLog,为 0 表⽰MTR包含⼀组RedoLog,如下图所⽰:

3.事务与Mini-Transaction是什么关系?

Mini-Transaction是包含的是⼀个DML操作对应的⼀组RedoLog,⽽⼀个事务中可能会包含多个DML操作,所以⼀个事务中包含⼀个或多个SQL语句,⼀个SQL语句包含⼀个或多个MRT,⼀个MTR包含⼀条或多条RedoLog,他们之间的关系如下图所⽰:

 6.RedoLog是如何写⼊缓冲区的?

前置知识:
这个问题可以理解为RedoLog的写⼊过程,要了解写⼊过程,必须先介绍RedoLog在内存和⽂件中是如何进⾏描述和组织的,我们提出以下⼏个问题:
1.⽤来组织RedoLog的数据结构是什么?
(1) ⽤来组织RedoLog的数据结构是Redo⻚,⻚的⼤⼩是 512B ,也可以称为⼀个 Redo Log
Block ,这个⼤⼩刚好对应磁盘上⼀个扇区,当⽇志写⼊磁盘时可以保证连续性 Redo Log
Block 的⽰意图如下所⽰:

(2)在⼀个 Redo Log Block 中,包含⽤来存储管理信息的块头 Log Block Header (占12Byte)

和块尾 Log Block Trailer (占4Byte),其他的空间是真正⽤来存储⽇志的区域 Log Block Body (占496B)
2.Log Block Header和Log Block Trailer都记录了哪些信息?
Log Block Header Log Block Trailer 包含的信息如下图所⽰:

(1)Log Block Header
  1.LOG_BLOCK_HDR_NO :Block的唯⼀标识,是⼀个⼤于0的值,取值范围1~0x40000000UL,⽽0x40000000UL对应的整数是1073741824即1GB,也就是说InnoDB最多能够⽣成1GB个⽇志块,每个⽇志块为512B,所以InnoDB允许维护⽇志的最⼤容量为 512GB ,在后⾯介绍配置⽇志相关的选项时,关于⽇志容量的⼤⼩就是以此为依据;
  2.LOG_BLOCK_HDR_DATA_LEN :表⽰Block中已经使⽤了多少字节,由于块头占⽤了12B的空间,所以初始值为12,当 Log Block Body 被全部写满时那么这个值就是512;
  3.LOG_BLOCK_FIRST_REC_GROUP :如果⼀个MTR会⽣产多条redo⽇志记录,这些⽇志记录被称之为⼀个redo⽇志记录组, LOG_BLOCK_FIRST_REC_GROUP 代表该Block中第⼀个MTR中第⼀条⽇志的偏移量。
  4.LOG_BLOCK_CHECKPOINT_NO :表⽰检查点的编号,关于检查点后⾯会详细详解
(2)Log Block Trailer
LOG_BLOCK_CHECKSUM :表⽰Block的校验和,⽤于正确性校验。
3.Redo Log Block在Log Buffer中是如何组织的?
在内存中RedoLog存储在⽇志缓冲区(Log Buffer)中,⽇志缓冲区是服务器启动时向操作系统申请的⼀⽚连续的内存区域,并被划分成若⼲个连续的 Redo Log Block ,⽤来存储即将要写⼊磁盘⽇志⽂件的数据,如下图所⽰

⽇志缓冲区⼤⼩可以通过系统变量 innodb_log_buffer_size 指定,默认⼤⼩为 16MB ,取
值范围1048576(1MB) ~ 4294967295(4GB)
# 查看当前Log Buffer的⼤⼩
mysql> show variables like 'innodb_log_buffer_size';
+------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set, 1 warning (0.05 sec)
# 设置Log Buffer的⼤⼩
mysql> set persist innodb_log_buffer_size =33554432;
Query OK, 0 rows affected (0.04 sec)

 分析过程:

向⽇志缓冲区中写⼊⽇志是⼀个顺序写⼊的过程,也就是从缓冲区的第⼀个 Redo Log Block
Log Block Body 开始依次向后写,⼀个block的空间空间⽤完之后再写下⼀个block,那么
有⼀个⾸先要解决的问题,当有⼀记⽇志需要写⼊缓冲区时,应该往哪个block中的哪个位置写呢?
1. 从⽇志缓冲区写RedoLog时从内存中的哪个地址开始写?
InnoDB 的提供了⼀个名为 buf_free 的全局变量,该变量表⽰后续写⼊⽇志在 Log Buffer
中的起始位置,如图所⽰:

2.不同的事务在并发执⾏时如何记录RedoLog?

(1)InnoDB以MTR为单位记录Redo Log,⼀个事务中包含多个MTR,⼀个MTR包含多条RedoLog,这些RedoLog是⼀个不可分割的⽇志组;
(2)⼀个事务在执⾏过程中并不是每⽣成⼀条Redo Log就写⼊到Log Buffer中,⽽是把⽣成的RedoLog先缓存在内存的⼀个区域中,当⼀个MTR执⾏完成后把这组⽇志⼀起复制到Log Buffer;
(3)假设有两个事务T1, T2并发执⾏,每个事务中都包含2个MRT,即事务T1包含mtr_t1_1和
mtr_t1_2,T2包含mtr_t2_1和mtr_t2_2,如下图所⽰:

(4)在并发环境下不同事务中的MTR是交替执⾏的,当MTR执⾏完成之后对应⽣成的RedoLog会被写⼊Log Buffer,所以在Log Buffer中⽇志的写⼊形式如下图所⽰:

(5)需要说明⼀点,不同的MTR产⽣的⽇志组占⽤的存储空间可能不⼀样,有的MTR产⽣的⽇志很少,有的MTR产⽣的⽇志量⾮常多。
解答问题
1.RedoLog在内存中⽤Redo⻚进⾏组织,称为 Redo Log Block ,每个 Redo Log Block
⼩固定为512B,对应磁盘上⼀个扇区,⽇志被顺序安排在 Log Block Body 中;
2.在Log Buffer中多个 Redo Log Block 顺序排列, Redo Log Block 的个数由Log Buffer的
⼤⼩决定;
3.当执⾏事务时,不同的语句对应不同的数据库操作,⼀条SQL语句可能包含多个MTR,⼀个MTR包含多条RedoLog,MTR中的多条⽇志称为⼀个⽇志组,写⼊Log Buffer的⽇志是以MTR对应的⽇志组为⼀个单位,这组⽇志不可分割。

7.Redo Log的刷盘时机?

前置知识

Redo Log的落盘条件

1.当MTR中包含的日志组完整的保存在内存中

2.当事务提交之前,事务对应的日志必须要落盘

分析过程

当⼀个MTR执⾏完成后,RedoLog会被写⼊Log Buffer,⽽Log Buffer⼤⼩是有限的,并且这些记录⽇志的⽬的是为了服务器崩溃后的数据恢复,在内存中保存也不安全,所以把它们刷到磁盘上进⾏保存
解答问题
InnoDB在以下情况会把RedoLog刷到磁盘:
(1)Log Buffer 空间不⾜时:Log Buffer⼤⼩是有限的,可以通过系统变量
innodb_log_buffer_size 设置,如果当前Log Buffer中的RedoLog占⽤了Log Buffer总容量⼀半左右会触发刷盘;
(2)事务提交时:当事务提交时,事务中对应的MTR已经完全记录在了Log Buffer中,在数据真正落盘之前,需要把对应的RedoLog刷新到磁盘;
(3)后台线程定时刷盘:后台的 Master Thread 线程,⼤约每秒都会把Log Buffer中的RedoLog刷新到磁盘;
(4)正常关闭服务器时:在服务关闭之前会把会把Log Buffer中的RedoLog刷新到磁盘;
(5)做检查点( checkpoint )操作时:关于 checkpoint 后⾯会详细介绍
衍⽣问题
1. 刷盘策略可以进⾏配置吗? 可以
(1)⽇志缓冲区的内容定期刷新到磁盘,可以通过系统变量 Innodb_flush_log_at_timeout=N
设置,N默认为1,单位为秒;
(2)通过设置系统变量 innodb_flush_log_at_trx_commit 设置写⼊和刷盘策略,默认值为1
      0 :⽇志每秒写⼊系统缓冲区并刷新到磁盘,未写⼊系统缓冲区的事务⽇志可能会在MYSQL崩溃时丢失;
      1 :⽇志在每次事务提交时写⼊系统缓冲区并刷新到磁盘;
      2 :⽇志在每次事务提交后写⼊系统缓冲区并每秒⼀次刷新到磁盘,未刷新到磁盘的⽇志可能在系统崩溃时丢失。
(3)如果启⽤⼆进制⽇志且设置 sync_binlog = 1 时,则必须设置 innodb_flush_log_at_trx_commit = 1
2. 不同的刷盘策略有什么影响?
⾸先看⼀下Log Buffer、操作系统缓存和磁盘中⽇志⽂件的关系,如图所⽰:

这⾥主要讨论系统变量 innodb_flush_log_at_trx_commit 对应的⼏种情况:
(1)值为0时:表⽰⽇志每秒写⼊操作系统缓存并刷新到磁盘,如果MySQL崩溃,那么在⼀秒内没有写⼊操作系统缓存的Redo Log将会丢失;
(2)值为2时:⽇志在每次事务提交后写⼊系统缓冲区并每秒⼀次刷新到磁盘,此时已提交的事务Redo Log全部都写⼊了操作系统缓存,MySQL⽆论是否崩溃,Redo Log都会以指定的时间刷新到磁盘,但是如果服务器崩溃或断电,将会导致操作系统缓存中的Redo Log丢失;
(3)值为 1 时:⽇志在每次事务提交时写⼊系统缓冲区并刷新到磁盘,此时Redo Log从Log Buffer中写⼊操作系统缓存并⽴即刷新到磁盘,从⽽尽可能的保证⽇志的完整性,推荐使⽤。

8.Redo Log对应磁盘上的⽂件是什么?

分析过程:

1.重做⽇志⽂件位于数据⽬录下的 #innodb_redo ⽬录中
2.重做⽇志⽂件分为普通类型和备⽤类型,普通类型是正在使⽤的⽇志⽂件,备⽤是准备使⽤的⽇志⽂件,InnoDB 共维护 32 个重做⽇志⽂件,每个⽂件的⼤⼩等于 1/32 *
innodb_redo_log_capacity
3.重做⽇志⽂件使⽤ #ib_redo N 命名约定,其中 N 是重做⽇志⽂件编号,备⽤的重做⽇志⽂件使⽤ _tmp 为后缀。如下⽰例显⽰有21个活动(普通)重做⽇志⽂件和11个备⽤重做⽇志⽂件:
root@guangchen-vm:/var/lib/mysql/#innodb_redo# ls
'#ib_redo582' '#ib_redo590' '#ib_redo598' '#ib_redo606_tmp'
'#ib_redo583' '#ib_redo591' '#ib_redo599' '#ib_redo607_tmp'
'#ib_redo584' '#ib_redo592' '#ib_redo600' '#ib_redo608_tmp'
'#ib_redo585' '#ib_redo593' '#ib_redo601' '#ib_redo609_tmp'
'#ib_redo586' '#ib_redo594' '#ib_redo602' '#ib_redo610_tmp'
'#ib_redo587' '#ib_redo595' '#ib_redo603_tmp' '#ib_redo611_tmp'
'#ib_redo588' '#ib_redo596' '#ib_redo604_tmp' '#ib_redo612_tmp'
'#ib_redo589' '#ib_redo597' '#ib_redo605_tmp' '#ib_redo613_tmp'

 4.每个普通的重做⽇志⽂件都与⼀个特定的 LSN 取值范围相关联,⽤于崩溃恢时快速定位到要执⾏重做的⽇志,可以使⽤下⾯的查询显⽰活动重做⽇志⽂件的 START_LSN END_LSN 值;

mysql> SELECT FILE_NAME, START_LSN, END_LSN FROM
performance_schema.innodb_redo_log_files;
+----------------------------+--------------+--------------+
| FILE_NAME | START_LSN | END_LSN |
+----------------------------+--------------+--------------+
| ./#innodb_redo/#ib_redo582 | 117654982144 | 117658256896 |
| ./#innodb_redo/#ib_redo583 | 117658256896 | 117661531648 |
| ./#innodb_redo/#ib_redo584 | 117661531648 | 117664806400 |
| ./#innodb_redo/#ib_redo585 | 117664806400 | 117668081152 |
| ./#innodb_redo/#ib_redo586 | 117668081152 | 117671355904 |
| ./#innodb_redo/#ib_redo587 | 117671355904 | 117674630656 |
| ./#innodb_redo/#ib_redo588 | 117674630656 | 117677905408 |
| ./#innodb_redo/#ib_redo589 | 117677905408 | 117681180160 |
| ./#innodb_redo/#ib_redo590 | 117681180160 | 117684454912 |
| ./#innodb_redo/#ib_redo591 | 117684454912 | 117687729664 |
| ./#innodb_redo/#ib_redo592 | 117687729664 | 117691004416 |

 解答问题:

1.重做⽇志⽂件位于数据⽬录下的 #innodb_redo ⽬录中,在MySQL8.0中InnoDB 共维护 32 个重做⽇志⽂件,每个⽂件的⼤⼩等于 1/32 * innodb_redo_log_capacity
2.重做⽇志⽂件分为普通类型和备⽤类型,并且使⽤ #ib_redo N 命名约定,其中 N 是重做⽇志⽂件编号,备⽤的重做⽇志⽂件使⽤ _tmp 为后缀
3.重做⽇志的总容量可以通过系统变量 innodb_redo_log_capacity 设置,8.0.34版本开始最
⼤为512GB

衍⽣问题
1.这么多⽇志⽂件⽇志写到哪个⽂件中?
通过查看 #innodb_redo ⽬录,可以看到系统⽣成了32个RedoLog⽂件,当RedoLog从内存刷到磁盘时,先从第⼀个⽇志⽂件开始写,第⼀个写满之后顺序写到第⼆个,以此类推;如果最后⼀个也写满了,就会重新从第⼀个⽂件开始写,也就是说重做⽇志⽂件可以循环使⽤,如图所⽰:

如果循环写⼊的话,那么后写⼊的⽇志会不会把之前写⼊的内容覆盖了?当然有这个可能,为了解决这个问题,InnoDB提出checkpoint的概念
2. 什么是LSN?
(1) LSN是 Log Sequence Number 的简写,称为⽇志序号;
(2)MySQL在运⾏期间,只要执⾏DML操作就会修改数据⻚,意味着会不断的⽣成RedoLog,InnoDB为了记录⽣成的⽇志总量(字节数),设计了⼀个只增不减的全局变量,这个全局变量就是LSN,起始值: 16*512 = 8192 ,最⼤值 2^64 - 1
(3)当⼀个MTR所包含的⼀组RedoLog被记录在 Redo Log Block 中时,实际是保存在 Log
Block Body 区域,但是在统计LSN增量时,如果MTR跨 Block 保存时,是按照实际写⼊的⽇
志⼤⼩加上 Log Block Header 所占的12Byte)和块尾 Log Block Trailer 所占4Byte;
(4)⽰例:
a. 系统启动后初始化Log Buffer,buf_free指向第⼀个block偏移量为12Byte的位置,也就是
block Header之后,此时LSN也会增加12,即8192 + 12 = 8204
b. 假设MTR_1中包含的⼀组RedoLog⼤⼩为200Byte,那么LSN就会在原来的基础上加200,即:8204 + 200 = 8404
c. 假设MTR_2中包含的⼀组RedoLog⼤⼩为1000Byte,这⾥当前的Block_1已经放不下这个
MTR,于是⽇志顺序保存在后⾯的Block中,占满第⼆个Block后,直到使⽤了第三个Block的
⼀部分空间,⽇志保存完成;
这时LSN不但要记录MTR_2中⽇志的总⼤1000Byte,还要记录Block_1+Block_2的Log Block
Trailer和Block_2+Block_3的Log Block Header,总⼤⼩为:1000 + 12 * 2 + 4 * 2 = 1032,此时LSN的值为:8404 + 1032 = 9436,如下图所⽰:

9.Redo Log⽇志⽂件的格式?

分析过程:

1.Log Buffer中的Redo Log Block与磁盘中的Redo Log Block有哪些不同? 

(1)在内存中Log Buffer是⼀⽚连续的内存空间,被划分成了若⼲个 512 字节⼤⼩的 Redo Log Block ⽤来保存Redo Log,将Log Buffer中的Redo Log刷新到磁盘,本质就是把 Redo Log Block 的写⼊⽇志⽂件中,所以Redo Log对应的⽇志⽂件其实也是由若⼲个 512 字节⼤⼩的 block 组成。MySQL会根据配置⽣成⼀组撤销⽇志⽂件,每个⽂件的格式和⼤⼩都⼀样,由两部分组成:
    管理区:前 2048 个字节,也就是前4个block存储⼀些⽇志⽂件的管理信息
    数据区:从第2048字节往后是⽤来存储Log Buffer对应的 Redo Log Block
(2)也就是说真实的⽇志是从每个⽇志⽂件的第2048个字节开始写⼊,如图所⽰

(3)所以Log Buffer中的Redo Log Block与磁盘中的Redo Log Block在结构上是相同的,只不过在磁盘上多了⽤于⽂件管理的⽂件头信息

解答问题:
磁盘中RedoLog的格式与内存中的格式相同,在内存中Log Buffer是⼀⽚连续的内存空间,被划分成了若⼲个 512 字节⼤⼩的 Redo Log Block ⽤来保存Redo Log,将Log Buffer中的Redo Log刷新到磁盘,本质就是把 Redo Log Block 的写⼊⽇志⽂件中,所以Redo Log对应的⽇志⽂件其实也是由若⼲个 512 字节⼤⼩的 block 组成,只不过在磁盘上多了⽤于⽂件管理的⽂件头信息
衍⽣问题
1. 重做⽇志⽂件管理区包含哪些信息?
关于 Redo Log Block :的结构与内存结构相同,前 2048 字节 分为4个Block分别为:
     LOG_CHECKPOINT_1 :第⼀个⽇志⽂件中⽇志头的第⼀个检查点信息
     LOG_ENCRYPTION ⽇志⽂件头信息中的加密信息
     LOG_CHECKPOINT_2 :第⼀个⽇志⽂件中⽇志头的第⼆个检查点信息
     LOG_FILE_HDR_SIZE :⽇志⽂件头信息

2.管理区中具体管理了什么信息?

管理区各字段中的信息随着MySQL版本迭代变化⾮常⼤,这⾥主要介绍⼀些关键信息
(1)LOG_CHECKPOINT_1 LOG_CHECKPOINT_2 :主要是记录CHECKPOINT操作时对应的LSN,LSN会交替写⼊到 LOG_CHECKPOINT_1 LOG_CHECKPOINT_2 中,具体写⼊规则后⾯介绍
(2) LOG_ENCRYPTION  : LOG_FILE_HDR_SIZE 中的加密信息,不做过多讨论
(3)(LOG_FILE_HDR_SIZE :主要记录⽇志⽂件的⼀些信息,主要包括:
    LOG_HEADER_FORMAT :占4字节,⽇志的格式标识,和MySQL版本相关,有重⼤更新的版本才设置相应的值,在MySQL5.7.9之前⼀直都是0
     LOG_HEADER_START_LSN :占8字节,⽇志⽂件中第⼀个LSN编号和最后一个LSN
     LOG_HEADER_CREATOR :占32字节,记录⽇志的创建者,正常⽣成的⽇志⼀般 为"MEB"+MySQL的版本号,如果是运⾏ mysqlbackup 程序,在备份过程中⽣成的⽇志,则
记录MySQL的版本号

10.什么是CHECKPOINT - 检查点?

分析过程:

RedoLog从内存刷到磁盘上的⽇志⽂件使⽤循环写⼊的⽅式,也就是从第⼀个⽇志⽂件顺序写到最后⼀个⽇志⽂件,当最后⼀个⽇志⽂件写满时⼜重新写第⼀个⽇志⽂件,那么就可能出现⽇志被覆盖的情况,那么哪些⽇志可以被覆盖哪些不能被覆盖呢?

1.哪些RedoLog可以被覆盖?

(1)⾸先回顾⼀下RedoLog的作⽤,RedoLog是⽤作崩溃后恢复没有完成落盘的事务,也就是说当Buffer Pool中的脏⻚写⼊RedoLog,但数据⻚还没有落盘时发⽣的崩溃,当服务器重启之后可以根据RedoLog进⾏恢复,这也是RedoLog的应⽤时机,所以这种状态下的RedoLog不能被覆盖,如下图所⽰:

(2)如果缓冲池中的脏⻚在记录RedoLog之后,也完成了真正的落盘操作,那么相应的RedoLog就没有⽤了,所以这部分RedoLog就可以被覆盖,如下图所⽰:

(3)经过分析可以看出,判断⽇志⽂件中的RedoLog是否可以覆盖的依据是它对应的数据⻚是否已经刷新到磁盘。

2.如何记录可以覆盖的⽇志⽂件位置?

(1)前⾯介绍过InnoDB使⽤LSN是来记录RedoLog总字节数,在这个基础上InnoDB采⽤⼀个全局变量 checkpoint_lsn 来记录当前系统中可以被覆盖⽇志总量是多少,也就是说
checkpoint_lsn 记录已落盘脏⻚对应的⽇志结束时LSN的值,此时LSN⼩于
checkpoint_lsn 的RedoLog就可以被覆盖,如图所⽰:

(2)当脏⻚刷新到磁盘之后,重新计算 checkpoint_lsn 的操作,称为⼀次 CHECKPOINT 操作,也可以说是重置⼀次检查点,系统会⽤⼀个 checkpoint_no 变量记录发⽣ CHECKPOINT 操作的次数,每做⼀ CHECKPOINT 操作 checkpoint_no 就会加1
(3)由于RedoLog⽂件的⼤⼩是固定的,在系统启动时已经分配好了对应的 Redo Log Block ,所以很容易就可以根据 checkpoint_lsn 计算写⼊位置在⽇志⽂件中的偏移量

 

(4)关于检查点相关的 checkpoint_no checkpoint_lsn 以及写⼊偏移量的信息会被记录在
第⼀个⽇志⽂件的管理区,同时InnoDB规定,当checkpoint_no的值是偶数时写到
checkpoint1 中,是奇数时写到 checkpoint2 中。
解答问题:
CHECKPOINT 也称为检查点,由于RedoLog⽂件是可以循环使⽤的,当最后⼀个⽂件写满时⼜会从第⼀个⽂件开始写⼊,这必将导致⽼的⽇志被覆盖, CHECKPOINT 是标记已被刷新到磁盘的脏⻚刷对应的RedoLog可以被覆盖的⼀种操作,当⽇志的LSN⼩于已落盘脏⻚对应的LSN都可以被覆盖。
衍⽣问题
1. 如果没有⼩于 checkpoint_lsn 的⽇志时如何处理?
如果⽇志⽂件中没有⼩于 checkpoint_lsn 的⽇志时,表明⽇志⽂件已经使⽤完了,这时原来
的⽇志不能被覆盖,InnoDB会先优先刷新脏⻚到磁盘,再做 CHECKPOINT 操作,之后再继续进⾏⽇志记录。

11.重做⽇志还有哪些主要的配置项?

分析过程:

1.重做⽇志在磁盘上所占的空间可以通过系统变量 innodb_redo_log_capacity 控制,变量值
以字节为单位,最⼤值 549755813888 ,表⽰ 512GB ,可以在选项⽂件或在运⾏时使⽤ SET GLOBAL 语句进⾏设置,如下所⽰:
# 将RedoLog的最⼤容量设置为8GB
SET GLOBAL innodb_redo_log_capacity = 8589934592;

 2.重做⽇志的⽬录可以通过系统变量 innodb_log_group_home_dir 进⾏设置,如果没有指定则⽇志⽂件位于数据⽬录的 #innodb_redo ⽬录中,如果定义了

innodb_log_group_home_dir 变量,则⽇志⽂件存放在该⽬录下的 #innodb_redo ⽬录中;
# 默认数据⽬录
root@guangchen-vm:/var/lib/mysql# ll
total 92948
# ... 省略
drwxr-x--- 2 mysql mysql 4096 11⽉ 5 11:15 '#innodb_redo'/ # 重做⽇志⽬录
# ... 省略
解答问题:
根据实际应⽤场景通过配置对应的系统变量来指定 Redo Log 在磁盘上所占的空间的⼤⼩、所在⽬录等属性。
衍⽣问题:
1. 如何查看重做⽇志的状态?
(1) 通过状态变量 innodb_redo_log_capacity_resized 显⽰当前重做⽇志容量限制:

 

(2) 可以通过查询 performance_schema.innodb_redo_log_files 表来查看活动重做⽇志⽂

件的信息
mysql> SELECT * FROM performance_schema.innodb_redo_log_files\G
*************************** 1. row ***************************FILE_ID: 6FILE_NAME: .\#innodb_redo\#ib_redo6START_LSN: 19656704END_LSN: 22931456SIZE_IN_BYTES: 3276800IS_FULL: 0
CONSUMER_LEVEL: 0
1 row in set (0.00 sec)

 (3)通过使⽤ SHOW ENGINE InnoDB STATUS 访问 InnoDB 标准监视器输出中 LOG 部分查看有关Redo Log的信息

mysql> SHOW ENGINE INNODB STATUS\G
*************************** 1. row ***************************Type: InnoDBName:
Status:
=====================================
... # 省略
---
LOG
---
Log sequence number 21737291 # 当前的LSN
Log buffer assigned up to 21737291 # Log buffer中已分配的LSN 
Log buffer completed up to 21737291 # Log buffer中已使⽤完成的LSN
Log written up to 21737291 # 已写⼊操作缓存的LSN
Log flushed up to 21737291 # 已刷新到⽇志⽂件的LSN
Added dirty pages up to 21737291 # 已添加的脏⻚对应的LSN
Pages flushed up to 21737291 # 最新添加到刷新链表⻚对应的LSN
Last checkpoint at 21737291 # 最后⼀次做checkpoint的LSN
Log minimum file id is 6 # ⽇志⽂件最⼩的编号
Log maximum file id is 6 # 普通⽇志⽂件的最⼤编号
24 log i/o's done, 0.00 log i/o's/second # 写⼊数据和速度
... # 省略

 12.如何根据RedoLog进⾏崩溃恢复?

分析过程:
在MySQL正常运⾏时,RedoLog不仅发挥不了它的作⽤⽽且还会对服务器的性能造成影响,但是服务器⼀旦崩溃,在重新启动时,就可以根据RedoLog中的记录把数据⻚恢复到崩溃前的状态
1.如何确定哪些⽇志需要恢复?
前⾯我们介绍过每⼀次 CHECKPOINT 操作都会重新计算 checkpoint_lsn checkpoint_lsn 之前的⽇志表⽰已经被刷到磁盘数据⻚所⽣成的RedoLog,既然已被刷到磁盘,也就没有必要进⾏恢复,所以需要恢复的是 checkpoint_lsn 之后的⽇志
2.如何获取最新的 checkpoint_lsn 和恢复的起点?
RedoLog⽂件组中的第⼀个⽂件的管理信息中有两个block checkpoint1 checkpoint2
其中都存储了 checkpoint_lsn checkpoint_no 信息,每次做 CHECKPOINT 操作时,
会在这两个block中交替写⼊ CHECKPOINT 信息,只要需要把这两个block中保存的
checkpoint_no 值⽐较⼀下,哪个值⼤就表⽰哪个block存储的就是最近的⼀次checkpoint信
息。这样我们就能拿到最近发⽣的 checkpoint 对应的 checkpoint_lsn 值以及它在
RedoLog⽂件组中的偏移量 checkpoint_offset
3. 如何确认恢复的终点?
我们⽤之前已经掌握的内容分析⼀下这个问题,⾸先RedoLog是顺序写⼊的,当⼀个block写满了之后再写下⼀个,⽽每⼀个block的 log block header 中都有⼀个名为
LOG_BLOCK_HDR_DATA_LEN 的属性,该属性记录了当前block使⽤了多少字节,对于写满的block来说,该值⼀定是 512 ,所以找到第⼀个 LOG_BLOCK_HDR_DATA_LEN 的值不为512,就可以确定恢复扫描的最后⼀个block,这个block中的最后⼀条⽇志就是恢复的终点。
4.如何进⾏恢复?
(1)确定了需要扫描哪些⽇志进⾏崩溃恢复之后,接下来就是怎么进⾏恢复了,假设现在的⽇志⽂件中有RedoLog,如图所⽰

(2)第⼀条⽇志在 checkpoint_lsn 之前,表⽰已经落盘不⽤恢复;
(3)checkpoint_lsn 之后的⽇志可以通过顺序扫描的⽅式,根据⽇志记录的内容依次恢复对应的数据⻚
(4)InnoDB在顺序读取⽇志进⾏恢复的过程中采⽤了⼀些优化措施:⾸先根据⽇志的 Space Id 和Page No 计算出散列值,以这个散列值为 KEY ,把 Space Id Page No 相同的⽇志放到哈希表的同⼀个槽⾥,如果有多个 Space Id Page No 相同的⽇志,那么按照⽇志⽣成的先后顺序使⽤链表连接起来,如下图所⽰:

(5)组织好⽇志后,通过遍历哈希表,就可以⼀次把⼀个数据⻚中的修改全部恢复好,减少了读取数据⻚时的随机I/O次数
5.如何确定哪些⽇志在崩溃前已经落盘?
(1)checkpoint_lsn 之后的⽇志有可能就根本没有落盘,也有可能已经落盘但没有来的及做
CHECKPOINT ,在恢复时如何区分呢?
(2)在⻚结构章节介绍过,磁盘上的每个⻚都包含⼀个 File Header 信息,其中⼜包含已被刷到磁盘的LSN: FIL_PAGE_FILE_FLUSH_LSN 信息,在恢复时就可以通过当前⽇志对应的LSN与FIL_PAGE_FILE_FLUSH_LSN 进⾏⽐较,如果⽇志的LSN⼩于等于已刷新到磁盘的LSN,那就证明⽇志对应的数据在崩溃之前已经落盘,直接跳过即可
解答问题
恢复的过程主要分为以下⼏步:
1. 通过 checkpoint_lsn 和第⼀个没有写满的⽇志⻚确定需要恢复⽇志的起始和结束位置;
2. 遍历⽇志并把Space Id 和 Page No相同的⽇志组织在⼀起,以便⼀次性恢复完相应数据⻚的所有内容;
3. ⽇志的LSN⼩于磁盘数据⻚⽂件记录的已刷新LSN时,表⽰这些数据在崩溃之前已落盘,跳过即可。

小结

1.RedoLog⽤于在数据库崩溃后恢复已提交事务还没有来的及落盘的数据,在保证事务的持
久性和⼀致性⽅⾯起到了⾄关重要的作⽤
2.RedoLog的写⼊时候,在UndoLog之后,脏⻚落盘之前
3.RedoLog的由 Type Space ID Page no data
4.⽤来组织RedoLog的数据结构是Redo⻚,⻚的⼤⼩是 512B ,由 Log Block Header Log Block Body Log Block Trailer 组成,⽇志内容保存在 Log Block Body
5.在Log Buffer和⽇志⽂件中Redo⻚的格式相同并且都是顺序排列的
6.RedoLog在磁盘上所占的空间可以通过系统变量 innodb_redo_log_capacity 控制,变量值以字节为单位,最⼤ 512 GB

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/59882.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux挖矿病毒(kswapd0进程使cpu爆满)

一、摘要 事情起因:有台测试服务器很久没用了&#xff0c;突然监控到CPU飙到了95以上&#xff0c;并且阿里云服务器厂商还发送了通知消息&#xff0c;【阿里云】尊敬的xxh: 经检测您的阿里云服务&#xff08;ECS实例&#xff09;i-xxx存在挖矿活动。因此很明确服务器中挖矿病毒…

变电站接地电阻监测装置-输电铁塔接地电阻监测装置:实时监测,预防故障

变电站接地电阻监测装置 接地电阻对电力系统的安全和稳定性至关重要&#xff0c;但在高压环境和极端气候下&#xff0c;接地系统可能出现性能下降&#xff0c;增加故障和跳闸的风险。传统的人工检测方法常常无法及时发现这些问题&#xff0c;并且操作繁琐。为此&#xff0c;我…

练习LabVIEW第四十三题

学习目标&#xff1a; 模拟红绿灯&#xff0c;红灯亮十秒&#xff0c;绿灯亮五秒&#xff0c;交替&#xff0c;并用波形图将波形显示 开始编写&#xff1a; 前面板 两个指示灯&#xff0c;一个红色&#xff0c;一个绿色&#xff0c;一个波形图&#xff1b; 程序框图 创建…

MySQL45讲 第十一讲 怎么给字符串字段加索引?

文章目录 MySQL45讲 第十一讲 怎么给字符串字段加索引&#xff1f;一、引言二、前缀索引&#xff08;一&#xff09;概念与创建方式&#xff08;二&#xff09;数据结构与存储差异&#xff08;三&#xff09;确定前缀长度的方法 三、前缀索引对覆盖索引的影响四、其他索引创建方…

STM32CUBEIDE FreeRTOS操作教程(八):queues多队列

STM32CUBEIDE FreeRTOS操作教程&#xff08;八&#xff09;&#xff1a;queues多队列 STM32CUBE开发环境集成了STM32 HAL库进行FreeRTOS配置和开发的组件&#xff0c;不需要用户自己进行FreeRTOS的移植。这里介绍最简化的用户操作类应用教程。以STM32F401RCT6开发板为例&#…

2.Python解释器

python解释器程序&#xff0c;用来翻译python代码&#xff0c;并提交给计算机执行。 上一篇博客就是安装了python解释器程序 写一个python文件&#xff0c;在文件中写入多行代码并执行&#xff1a; 进入python后&#xff0c;输入exit()命令退出

JAVA笔记 | ResponseBodyEmitter等异步流式接口快速学习

先简单记录下简单使用跟测试&#xff0c;后续再补充具体&#xff0c;最近有用到&#xff0c;简单来说就是后端(服务端)编写个发射器&#xff0c;实现一次请求&#xff0c;一直向前端客户端发射数据&#xff0c;直到发射器执行完毕&#xff0c;模拟ai一句一句回复的效果 Respon…

Liunx:文件fd、重定向、管道

文件fd&#xff1a; 操作系统运行中一定存在着许多被打开的文件&#xff0c;这些文件需要被管理。一个进程会打开若干个文件。一个文件如果在操作系统中被打开&#xff0c;那么必须给该文件创建一个文件对象&#xff0c;包含被打开文件的各种属性。那么进程与文件的关系就变成…

linux笔记(DNS)

一、概念 DNS&#xff08;Domain Name System&#xff09;DNS 是一种分布式网络目录服务&#xff0c;主要用于将人类易于记忆的域名&#xff08;如 www.example.com&#xff09;转换为计算机可识别的 IP 地址&#xff08;如 192.168.1.1&#xff09;。它就像是互联网的电话簿&a…

优衣库在淘宝平台的全方位竞品分析与店铺表现研究:市场定位与竞争策略透视

优衣库品牌在淘宝平台的全方位竞品与店铺表现分析 一、品牌商品分析 1.商品列表与分类分析&#xff08;数据来源&#xff1a;关键词商品搜索接口&#xff1b;获取时间&#xff1a;2024.08.30&#xff09; 商品类别分布柱状图&#xff1a; 根据关键词商品搜索接口获取到的优衣…

RocketMQ 自动注入消费者

目录 前言一、情景介绍二、问题分析三、代码实现 前言 之前接到一个需求&#xff0c;我们项目的技术负责人希望通过配置的形式&#xff0c;在项目启动的时候自动根据配置生成对应的消费者 觉得还有点意思&#xff0c;随即记录一下~ 一、情景介绍 比如我这里有一个消费者 Mes…

数据结构(C语言版)(第2版) 课后习题答案 李冬梅

数据结构(C语言版)(第2版) 第1章 绪论 1.简述下列概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型。 答案: 数据:是客观事物的符号表示,指所有能输入到计算机中并被计算机程序处理的符号的总称。如数学计算中用到的整数和实数…

Vue 自定义icon组件封装SVG图标

通过自定义子组件CustomIcon.vue使用SVG图标&#xff0c;相比iconfont下载文件、重新替换更节省时间。 子组件包括&#xff1a; 1. Icons.vue 存放所有SVG图标的path 2. CustomIcon.vue 通过icon的id索引对应的图标 使用的时候需要将 <Icons></Icons> 引到使用的…

吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)4.9-4.10

目录 第四门课 卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;第四周 特殊应用&#xff1a;人脸识别和神经风格转换&#xff08;Special applications: Face recognition &Neural style transfer&#xff09;4.9 内容代价函数&#xff08;Content cos…

界面控件DevExpress WPF中文教程:Data Grid——卡片视图设置

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

LLM训练”中的“分布式训练并行技术;分布式训练并行技术

目录 “LLM训练”中的“分布式训练并行技术” 分布式训练并行技术 数据并行 流水线并行:按阶段(stage)进行切分 张量并行 序列并行 多维混合并行 自动并行 MOE并行 重要的分布式AI框架 “LLM训练”中的“分布式训练并行技术” 随着深度学习技术的不断发展,特别是…

Ubuntu开启FTP与SSH服务

在配置开发环境时&#xff0c;这两个配置感觉是最有用的&#xff0c;开启FTP服务可以将远程linux上的文件映射到Windows上&#xff0c;不管是使用虚拟机还是嵌入式linux设备&#xff0c;特别在开发写代码的时候&#xff0c;映射到Windows上使用VS code打开编写比在linux上编写舒…

虚拟现实技术及其在教育领域的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 虚拟现实技术及其在教育领域的应用 虚拟现实技术及其在教育领域的应用 虚拟现实技术及其在教育领域的应用 引言 虚拟现实技术概述…

搜维尔科技:Varjo XR-4在教育科研领域应用

医学教育与培训&#xff1a; • 解剖学教学&#xff1a;传统的解剖学教学依赖于教科书、图片或实体标本&#xff0c;学生对于人体结构的空间关系理解存在一定难度。而使用Varjo头显&#xff0c;学生可以沉浸在虚拟的人体解剖环境中&#xff0c;全方位、多角度地观察人体的各个…

Java 源码中的 Unicode 逃逸问题,别被注释给骗了

背景 看了一段项目源码&#xff0c;定义了一个 List 对象&#xff0c;往该列表对象 add 的代码前面有注释符号&#xff0c;但是程序运行时列表中却存在对象&#xff0c;为什么呢&#xff1f;仔细看了一下&#xff0c;注释符号和 add 代码之间有一个特殊符号 \u000d&#xff0c…