当前位置: 首页 > article >正文

InnoDB 存储引擎<五>undo log, redo log,以及双写缓冲区

目录

撤销⽇志 - Undo Log

双写缓冲区 - Doublewrite Buffer

重做⽇志 - Redo Log 

本篇是继承自上篇InnoDB存储引擎的磁盘文件

上篇链接:InnoDB 存储引擎<四>磁盘文件一

撤销⽇志 - Undo Log

1.什么是撤销⽇志?

解答问题:

1.当事务对数据进⾏修改的时候,每个修改操作都会在磁盘上创建与之对应的Undo Log,当事务需要回滚时,会根据Undo Log逐⼀进⾏撤销操作,从⽽保证事务的原⼦性。也就是说撤销⽇志是为事务的回滚操作⽽诞⽣的机制,它是⼀个撤销操作记录的集合。
2.Undo⽇志保存在Undo⽇志段中,Undo⽇志段位于回滚段中,回滚段位于undo表空间和全局临时表空间中

 

衍⽣问题:
1. 撤销⽇志的写⼊时机?
在事务执⾏每个DML之前,会根据DML构建对应的撤销⽇志,并申请⼀个 undo log
segments (撤销⽇志段),把⽇志记录在申请到的撤销段中,再执⾏真正的DML操作,
执⾏过程如下所⽰:

2.撤销⽇志在撤销表空间中的组织形式是怎样的?

前置知识:
.Undo⽇志保存在Undo⽇志段中,Undo⽇志段位于回滚段中,回滚段位于undo表空间和全局临时表空间中
分析过程:
撤销⽇志在撤销表空间中的组织结构图,如下图所示

1.Undo log segments (撤销⽇志段)也称为撤销段,⼀个撤销⽇志段可以保存多个事务的回滚⽇志,但在同⼀时间只能被⼀个活跃事务使⽤,对应的空间在事务提交或回滚后才可以被重⽤。
2.rollback segments (回滚段)中包含撤销⽇志段,通常位于undo表空间和全局临时表空间
中,使⽤系统变量 Innodb_rollback_segments 可以定义分配给每个undo表空间和全局临时
表空间的回滚段的数量,默认值为128,取值范围是[1, 128];
3.⼀个回滚段⽀持的事务数取决于回滚段中的undo slots(槽数)和每个事务所需的undo⽇志数,⼀个回滚段中的undo槽数可以根据InnoDB⻚⾯⼤⼩进⾏计算,公式是(InnoDB Page Size / 16),⽐如默认情况下 InnoDB Page Size ⼤⼩为 16KB ,那么⼀个回滚段就可以包含 1024 undo slot ⽤来存储事务的撤销⽇志。
4.回滚段中还记录了 History List 的头节点 History List Base Node ,以及回滚段的⼤小
5.通过系统变量 innodb_rollback_segments 可以设置Undo表空间中的回滚段数量,最⼤值
和默认值都是128
# 查看Undo表空间中的回滚段数量
mysql> show variables like 'innodb_rollback_segments';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_rollback_segments | 128 |
+--------------------------+-------+
1 row in set, 1 warning (0.01 sec)

# 设置Undo表空间中的回滚段数量
mysql> SET GLOBAL innodb_rollback_segments = 128;
Query OK, 0 rows affected (0.00 sec)
解答问题:
撤销表空间中包含 rollback segments (回滚段),每个回滚段中包含若⼲undo slots(槽数),
每个槽对应⼀个 Undo log segments (撤销⽇志段),撤销⽇志段中包含具体的撤销⽇志

3.撤销⽇志的格式是怎样的?(撤销日志的结构) 

分析过程:
撤销⽇志格式⽰意图如下:与数据行的格式进行比较

解答问题:
条记录在Undo Log⻚中的Undo Log⽇志⼤体包含两部分:分别是记录了Undo类型、表ID、上 ⼀条、下⼀条⽇志的偏移地址等在内的"基本信息",以及记录了不同操作和数据的"操作信息"
衍⽣问题
1. 在事务中不同的DML操作对应的撤销⽇志是否不同?(不同的DML操作对应不同的撤销日志)
在执⾏DML语句操作数据库时,不同SQL语句对应的撤销操作不同,不同的撤销操作对应的Undo Log存储格式也不相同,按照增、删、改等不同的DML操作,⽣成对应的撤销⽇志
2.不同操作对应的撤销⽇志如何区分?
(1)Undo类型有很多种,最常⻅的就是增、删、改,分别⽤ TRX_UNDO_INSERT_REC
TRX_UNDO_DEL_MARK_REC TRX_UNDO_UPD_EXIST_REC 表⽰,示意图如下所⽰

 (2)新增( TRX_UNDO_INSERT_REC )时的Undo Log操作信息相对简单,只记录了主键值,主键⻓度等主键信息;

(3)删除( TRX_UNDO_DEL_MARK_REC )时除了记录主键信息之外,还记录了旧的事务ID,旧的ROLL_POINTER信息,⽤来构建有序的Undo版本链,还会记录⼀些被索引字段的信息;
(4)更新( TRX_UNDO_UPD_EXIST_REC )时较为复杂,如果不更新主键则和删除时类似,会记录主键信息、旧的事务ID、旧的ROLL_POINTER信息、被索引字段的信息和被更新的信息;如果更新了主键,则会记录两条Undo Log ,⼀条删除的和⼀条新增的;
对于更新主键的操作,本质上都是删除旧的数据行,新增一个新数据行

4.撤销⽇志是如何组织在⼀起的?(通过撤销日志页)

分析过程:

撤销⽇志的组织⽰意图如下:

对于这里的undo page header,undo log segment header和undo log header中存储的主要字段信息

解答问题:

1.⼀条条Undo Log会被逐⼀放在Undo Log⻚中,Undo Log⻚和其他类型的⻚⼀样都会包含头尾信息,除此之外还有Undo Log特有的信息,包括:
(1)UNDO PAGE HEADER :记录了Undo Log⻚类型、⽇志偏移位置,下⼀⻚链表引⽤等信息
(2)UNDO LOG SEGMENT HEADER :记录了回滚段信息
(3)UNDO LOG HEADER :记录了产⽣这条⽇志的事务Id:Trx ID;事务的提交顺序:Trx No和其他事务相关信息
2.在这三个特有的头信息之外,其他空间都会⽤来记录Undo Log⽇志,如果某个事务很⼤,⼀个Undo Log⻚没有办法完整记录,就需要申请新的Undo Log⻚,然后通过 UNDO PAGE HEADER 中链表引⽤信息链接到前⼀个⻚,后⾯的这些⻚只需要记录Undo Log并不需要记录Undo头信息。
3.这个由Undo Log构成的链表称做Undo链,在事务中会起到⾮常重要的作⽤。

 衍⽣问题:

1.事务提交后Undo Log是否就可以删除了?

对于新增操作所记录的Undo Log⽇志,在事务提交之后就可以直接删除了,⽽删除和更新的Undo Log⽇志还需要服务事务的MVCC,所以并不能直接删除,⽽是加⼊到  hisotry list 中。因些InnoDB为了最⼤程度节省空间提升效率对Undo Log进⾏了分类

5.撤销⽇志如何分类?

前置知识:

1.这里的分类是为了方便管理日志而进行的分类

2.关于上个问题中UNDO PAGE HEADER 中记录了Undo Log⻚类型,意义是啥

解答问题:
1.Undo Log分为两⼤类:⼀类只记录新增操作,事务提交后可以直接清除;另⼀类记录删除和更新操作,所以相应的回滚链也会被区分为2个:Insert Undo链 和 Update Undo链(Delete + Update)
2.另外普通表和临时表分别对应这两类Undo链,如是⼀个事务既有新增⼜有修改并且⽤到了临时表,那么这个事务最多可以分配四个撤销⽇志,也就是四个Undo链,分别是:
   (1)对⽤⼾定义的普通表进⾏ INSERT 操作
   (2)对⽤⼾定义的普通表进⾏ UPDATE DELETE 操作
   (3)对⽤⼾定义的临时表进⾏ INSERT 操作
   (4)对⽤⼾定义的临时表进⾏ UPDATE DELETE 操作
对于前两个是保存在系统或用户创建的撤销表空间,后两个是保存在临时表空间中,临时表空间中有一个回滚段专门用来保存undo 日志
3. 根据事务的操作按需要写⼊Undo⽇志,⽐如,在普通表和临时表执⾏ INSERT UPDATE 和 DELETE 操作的事务需要会写⼊以上四种类型的撤销⽇志;只在普通表上执⾏ INSERT 操作的事 务只需要⼀个撤消⽇志
4.对普通表执⾏操作的事务将从指定的系统表空间或undo表空间的回滚段分配undo⽇志。对临时表执⾏操作的事务从指定的临时表空间回滚段分配undo⽇志

6. InnoDB最⼤⽀持并发读写事务的数量如何计算?

 解答问题:

可以⽤以下公式计算InnoDB能够⽀持的并发读写事务的数量
(1) 如果每个事务执⾏ INSERT UPDATE DELETE 操作,注意只执⾏⼀种类型的操作,并发读 写事务数为:
# 最⼤⽀持 (16384 / 16) * 128 * 127 = 16,646,144
(innodb_page_size / 16) * innodb_rollback_segments * number of undo tablespaces

 从左向右为页大小,回滚段的数量以及撤销表空间的个数

(2)如果每个事务执⾏ INSERT UPDATE (和的意思为一个事务要使用两个撤销日志段)DELETE 操作,并发读写事务数为:

# 最⼤⽀持 (16384 / 16 / 2) * 128 * 127 = 8,323,072
(innodb_page_size / 16 / 2) * innodb_rollback_segments * number of undo tablespaces

 (3)如果⼀个事务在临时表上执⾏ INSERT 操作,并发读写事务数为:

# 临时表最⼤⽀持 (16384 / 16) * 128 = 131,072
(innodb_page_size / 16) * innodb_rollback_segments

 (4)如果⼀个事务在临时表上执⾏ INSERT UPDATE DELETE 操作,并发读写事务数为:

# 临时表最⼤⽀持 (16384 / 16 / 2) * 128 = 65,536
(innodb_page_size / 16 / 2) * innodb_rollback_segments

 7.如何理解Undo链?

解答问题:

1.Insert Undo链 和 Update Undo链采⽤了不同的组织⽅式;
2.对于新增操作,Insert Undo链中的每个Undo Log都会对应⼀条新的数据⾏,这个数据⾏中⽤ ROLL_POINTER 信息来关联Undo Log,在回滚时就可以通过它找到需要回滚的Undo Log了,即一条新增的数据行对应一条undo日志,他们之间是一对一的关系

3.对于删除和更新,Update Undo链中的每个Undo Log也都对应⼀个数据⾏,每次更新都会通过 Undo Log中的 ROLL_POINTER 进⾏关联,从⽽每个数据⾏都会构成⼀个Undo Log版本链,回滚的时候就可以依序撤销,这个版本链在事务的MVCC中起到了⾮常重要的作⽤,⽤于解决事务的"隔离性"

4.以下是⼀个关于更新操作的Undo链

 8.撤销⽇志为什么需要落盘?

分析过程:

1.在对数据进⾏修改时,都是在内存中操作的,也就是在Buffer Pool中修改对应的数据⻚,在修改数据⻚之前先把对应的撤销⽇志记录在内存中,如果此时事务回滚直接根据内存中的撤销⽇志做回滚操作即可;

2.在修改完成提交事务后,脏⻚进⾏落盘操作,此时事务已提交,不能回滚,所以撤销⽇志也就失效了;

3.当服务器崩溃时,如果事务没有提交,所有的修改都在内存中,还没有落盘,对于修改直接丢弃;如果事务已经提交,则根据重做⽇志和双写缓冲区中的备份进⾏恢复;
4.通过分析看上去撤销⽇志并不需要落盘,其实以上的分析场景并没有考虑到全部的场景,⽐如⼤事务的运⾏、MVCC中版本链什么时候可以销毁、事务的不同隔离级别等因素;
解答问题:undo log落盘必须在真实数据页落盘之前
1. 在运⾏⼤事务时,InnoDB为了避免⼤事务提交时统⼀落盘操作带来的性能问题,允许在事务进⾏ 的过程中就进⾏落盘操作并记录对应的UndoLog,当发⽣崩溃恢复时,通过回放UndoLog把未提 交的事务进⾏回滚;
2.如果⼀个事务已经提交,但还有其他事务需要访问版本链中对应的UndoLog,那么也需要把相应的撤销⽇志保存到 hisotry list 中。
3.不同隔离级别下,没有提交的事务也可能会落盘,回滚时依然要完成撤销操作
衍⽣问题
1. 撤销⽇志在内存中如何记录?
(1) 与数据⻚在内存中的保存⽅式相同,撤销⽇志在内存中也保存在Buffer Pool中,与磁盘中的 UndoLog⻚结构⼀致,内存中每个UndoLog⻚通过控制块管理
(2) 在内存中使⽤四个链表来管理正在使⽤的UndoLog⻚和空闲UndoLog⻚,根据不同的⽇志类型分 为:
     Insert List :正在被使⽤的⽤来管理Insert类型的UndoLog ⻚
     Insert Cache List :空闲的或被清理后可以被后续事务重⽤的Insert类型UndoLog⻚
    Update List :正在被使⽤的⽤来管理Update类型的UndoLog ⻚
    Update Cache List :空闲的或被清理后可以被后续事务重⽤的Update类型UndoLog⻚

2.撤销⽇志的写⼊过程是怎样的? ----先写内存,再按需落盘

(1)当写事务开始时,会先分配⼀个处理 ACTIVE 状态的 Rollback Segment
(2)当第⼀次DML操作产⽣Undo Record时,会轮询当前 Rollback Segment 中可⽤的 Slot ,以便获取⼀个 Undo Log Segment
(3)根据撤销⽇志的类型获取UndoLog⻚,并挂载到对应的List当中;
(4)在UndoLog⻚顺序写⼊⽇志,当⼀个UndoLog⻚写满之后,会获取新的UndoLog⻚以便继续写⼊当前事务⽣成的⽇志,这⾥注意:单条UndoLog不能跨⻚存储,也就是说当某条⽇志在当前⻚中放不下时,会整体保存下⼀⻚中;
(5)由后台线程把⽇志刷⼊磁盘;
(6)当事务结束之后(commit或者rollback), insert ⽇志类型对应的 Undo Log Segment
UndoLog page 会直接回收,⽽ update ⽇志类型对应的 Undo Log Segment
UndoLog page 会等待后台的清理操作完成后,确保⽇志不会有事务再访问后进⾏回收,回收的UndoLog⻚被挂载到Cache List中

3.撤销⽇志的回滚过程是怎样的?

(1)回滚操作可以是⽤⼾通过rollback主动触发,也可能发⽣在崩溃恢复时,不论是哪种触发条件,回滚操作都是相同的,基本过程就是读取该事务的Undo Log,从后向前依次进⾏逆向操作,从⽽恢复索引记录;
(2)对于 Insert 类型的回滚操作就是 Delete ,在删除的过程中会重新调整主键索引和⼆级索引;
(3)对于Update和Delete类型的回滚操作,主要是回退这次操作在所有主键索引和⼆级索引的影响,可能包括重新插⼊被删除的⼆级索引记录、去除⾏管理信息中的Delete Mark标记、将主索引记录修改回之前的值等;
(4)完成回滚的Undo Log会进⾏回收,将不再使⽤的UndoLog⻚的磁盘空间还给 Undo Log
Segment ,这个过程是写⼊过程的逆操作。
4.撤销⽇志的清理过程是怎样的?
(1)InnoDB通过保存多份Undo Log的历史版本来实现MVCC,当某个历史版本已经确认不会被任何现有的和未来的事务访问时,就应该被清理掉;
(2)当开启⼀个事务时都会被分配⼀个事务编号 trx_id ,⽽事务进⾏读操作时会创建⼀个
ReadView,并记录当前所有事务中的最⼩活跃事务编号 m_low_limit_id ,如果版本链中
志的 trx_id < m_low_limit_id ,则表⽰当前读操作发⽣时,⽇志对应的事务已提交,其修
改的新版本是可⻅的, 因此不再需要通过Undo版本链构建之前的版本,这个事务的Undo Log也就可以被清理了。
(3)Undo的清理⼯作是由专⻔的后台线程进⾏扫描和分发,并由多个线程进⾏清理,并可以通过系统变量 innodb_purge_threads 配置清理线程数,系统变量 innodb_purge_batch_size
可以配置每次清理的⻚数

 双写缓冲区 - Doublewrite Buffer

1.双写缓冲区的作⽤?

解答问题:
双写缓冲区是磁盘上的⼀个存储区域,当 InnoDB 将缓冲池中的数据⻚写⼊到磁盘上表空间数据⽂件之前,先将对应的⻚写到双写缓冲区;如果在数据真正落盘的过程中出现了意外退出,⽐如操作系统、存储⼦系统崩溃或异常断电的情况, InnoDB 在崩溃恢复时可以从双写缓冲区中找到⼀份完好的⻚副本

衍⽣问题:
1.双写缓冲区中的数据保存在哪⾥?
在MySQL 8.0.20之前, doublewrite 缓冲区位于InnoDB系统表空间中。从MySQL 8.0.20开
始, doublewrite 缓冲区默认存储区域位于数据⽬录下的 doublewrite ⽂件中。
root@guangchen-vm:/var/lib/mysql# ll
total 92948
drwxr-x--- 8 mysql mysql 4096 11⽉ 5 11:15 ./
drwxr-xr-x 73 root root 4096 10⽉ 30 12:07 ../
# ...省略
# 默认创建两个双写缓冲区⽂件
-rw-r----- 1 mysql mysql 196608 11⽉ 5 11:15 '#ib_16384_0.dblwr' # ⽂件1
-rw-r----- 1 mysql mysql 8585216 11⽉ 1 10:34 '#ib_16384_1.dblwr' # ⽂件2
# ...省略

 2.如何配置双写缓冲区?

解答问题:
1.是否启⽤ doublewrite 缓冲区可以通过系统变量 innodb_doublewrite[=ON|OFF] 控制,默认为启⽤,如果真实的业务场景更关注性能⽽不是数据完整性,可以考虑禁⽤doublewrite缓冲区,例如在执⾏测试的环境中;
2.doublewrite ⽂件所在⽬录通过系统变量 innodb_doublewrite_dir (MySQL 8.0.20中引⼊)指定,如果不指定则在 innodb_data_home_dir ⽬录(默认为data⽬录)下创建;如果指定
doublewrite⽬录,建议设置在最快的存储介质上,以提⾼效率;
root@guangchen-vm:/var/lib/mysql# ll
total 92948
drwxr-x--- 8 mysql mysql 4096 11⽉ 5 11:15 ./
drwxr-xr-x 73 root root 4096 10⽉ 30 12:07 ../
# ...省略
# 默认创建两个双写缓冲区⽂件
-rw-r----- 1 mysql mysql 196608 11⽉ 5 11:15 '#ib_16384_0.dblwr' # ⽂件1
-rw-r----- 1 mysql mysql 8585216 11⽉ 1 10:34 '#ib_16384_1.dblwr' # ⽂件2
# ...省略

命名⽅式为: #ib_page_size_file_number.dblwr ,以上 #ib_16384_0.dblwr 的⽂件 表⽰当前数据⻚的⼤⼩为16KB,编号为0

3.双写⽂件的数量通过系统变量 innodb_doublewrite_files 设置,默认情况下,为每个缓冲

池实例创建两个doublewrite⽂件,也就是说⽂件数量为 innodb_buffer_pool_instances * 2 ;此变量⽤于⾼级性能调优,⼤多数场景使⽤默认设置即可;

重做⽇志 - Redo Log 

1.重做⽇志的作⽤?

解答问题:
1.重做⽇志在保证事务的持久性和⼀致性⽅⾯起到了⾄关重要的作⽤
2.重做⽇志⽤于在数据库崩溃后恢复已提交事务还没有来的及落盘的数据。重做⽇志以⽂件的形式保存在磁盘上,在正常的操作过程中,MySQL根据受影响的记录进⾏编码并写⼊重做⽇志⽂件,这些数据称为"Redo",在重新启动时⾃动读取重做⽇志进⾏数据恢复。

衍⽣问题:
1.为什么要⽤Redo Log,⽽不是直接写磁盘?
(1)⾸先明确⼀点,我们对数据进⾏的DML操作都会包含在事务当中,当完成修改并且提交事务之后,在内存中被修改的数据⻚就要刷新到磁盘完成持久化;
(2)那么如果这次DML操作对应的修改开始刷盘的话,当服务器崩溃,没有被刷到磁盘的数据⻚就从内存中丢失,这时这个事务的修改在磁盘上就是不完整的,也就是没有保证事务的⼀致性
(3)为了解决这个问题,InnoDB在执⾏每个DML操作时,当内存中的数据⻚修改完成之后,把修改的内容以⽇志的形式保证在磁盘上,然后再对数据⻚进⾏真正的落盘操作,这样做就相当于对修改进⾏了⼀次备份,即使当服务器崩溃也不会受到影响,当服务器重启之后,可以从磁盘上的⽇志⽂件中找到上次崩溃之前没有来的及落盘的数据继续执⾏落盘操作;
(4)InnoDB引擎的事务采⽤了 WAL 技术 (Write-Ahead Logging) ,基本思想是先写⽇志,再写磁盘,只有⽇志写⼊成功,事务才算提交成功,这⾥的⽇志就是Redo Log。当发⽣宕机且数据未刷到磁盘的时候,可以通过Redo Log来恢复,保证ACID中的持久性,这也是Redo Log的作⽤。undo日志保证事务的原子性
2.Redo Log的写⼊时机?
当发⽣数据修改操作时追加重做⽇志,已落盘数据对应的⽇志位置被记录为⼀个检查点,检查点之前的数据被置为⽆效,所以重做⽇志⽂件可以循环使⽤。以⼀个更新操作为例,重做⽇志的写⼊过程与时机,如下图所⽰:

使用Log Buffer的原因:因为每次进⾏DML操作都会进⾏⼀次磁盘I/O,这样会严重影响效率,所以把⽇志统⼀写⼊内存中的Log Buffer,根据刷盘策略统⼀进⾏落盘操作,可以实
现⼀次磁盘I/O写⼊多条⽇志,从⽽提升效率。

2.Redo Log的格式是怎样的?

分析过程:

1.在介绍RedoLog的格式之前,先来分析⼀下RedoLog中需要记录哪些内容

(1)当进⾏DML操作时,⾸先要修改内存中的数据⻚,但是修改的数据有可能只是数据⻚中很少的⼀部分内容,甚⾄有可能只修改了⼏个字节,那么在RedoLog中是要记录整个数据⻚吗?当然不是,如果每次保存整个数据⻚的话就有太多的⽆⽤数据写⼊⽇志,严重影响效率⽽且浪费空间
(2)为了节省空间提⾼效率,RedoLog只记录被修改的内容,⽐如当前的DML修改了哪个表空间、表空间中的哪个数据⻚,数据⻚中多少偏移量处的值修改成了什么,⽐如:
# ⼀个例⼦
1 号表空间中的⻚编号为 50 的数据⻚中偏移量为 1000 处的整型值修改为 100
在示例中明确了当前日志对应的文件,要修改的起始位置,要修改的长度和新值
(3)这样就可以⽤很⼩的⽇志记录当前对数据⻚所做的修改,⼤⼤节省了空间
解答问题
1.RedoLog本质上只是记录了事务对数据库做了哪些修改,修改操作包含多种场景,⽐如对数据⾏、索引⻚的增删改,对范围的修改与删除等等,不同场景的 redo ⽇志定义了不同的类型,但是绝⼤部分类型的 redo ⽇志都有下边这种通⽤的结构包括:
   (1)Type : ⽇志类型, 1BTYE
   (2)Space ID : 操作所属的表空间, 4BTYE
   (3)Page no : 操作的数据⻚在表空间中的编号, 4BTYE
   (4)data :⽇志的内容,⻓度不固定

衍⽣问题:
1.data 部分的具体内容是什么?
data 部分⼜可以分为:数据⻚中的偏移量,修改内容的⻓度和具体的修改内容

 3.RedoLog的类型分为哪些?

分析过程:
查看RedoLog的类型,最完整最直观的⽅式就是通过阅读源代码,如下所⽰:
/** @file include/mtr0types.h
 Mini-transaction buffer global types
 Created 11/26/1995 Heikki Tuuri
 *******************************************************/
// 省略...
/** @name Log item types
The log items are declared 'byte' so that the compiler can warn if val
and type parameters are switched in a call to mlog_write_ulint. NOTE!
For 1 - 8 bytes, the flag value must give the length also! @{ */
enum mlog_id_t {
 /** if the mtr contains only one log record for one page,
 i.e., write_initial_log_record has been called only once,
 this flag is ORed to the type of that first log record */
 MLOG_SINGLE_REC_FLAG = 128,
 /** one byte is written */
 MLOG_1BYTE = 1,
 /** 2 bytes ... */
 MLOG_2BYTES = 2,
 /** 4 bytes ... */
 MLOG_4BYTES = 4,
 /** 8 bytes ... */
 MLOG_8BYTES = 8,
 /** Record insert */
 MLOG_REC_INSERT_8027 = 9,
 /** Mark clustered index record deleted */
 MLOG_REC_CLUST_DELETE_MARK_8027 = 10,
 /** Mark secondary index record deleted */
 MLOG_REC_SEC_DELETE_MARK = 11,
 /** update of a record, preserves record field sizes */
 MLOG_REC_UPDATE_IN_PLACE_8027 = 13,
/*!< Delete a record from a page */
 MLOG_REC_DELETE_8027 = 14,
 /** Delete record list end on index page */
 MLOG_LIST_END_DELETE_8027 = 15,
 /** Delete record list start on index page */
 MLOG_LIST_START_DELETE_8027 = 16,
 /** Copy record list end to a new created index page */
 MLOG_LIST_END_COPY_CREATED_8027 = 17,
 /** Reorganize an index page in ROW_FORMAT=REDUNDANT */
 MLOG_PAGE_REORGANIZE_8027 = 18,
 /** Create an index page */
 MLOG_PAGE_CREATE = 19,
 /** Insert entry in an undo log */
 MLOG_UNDO_INSERT = 20,
 /** erase an undo log page end */
 MLOG_UNDO_ERASE_END = 21,
 /** initialize a page in an undo log */
 MLOG_UNDO_INIT = 22,
 /** reuse an insert undo log header */
 MLOG_UNDO_HDR_REUSE = 24,
 /** create an undo log header */
 MLOG_UNDO_HDR_CREATE = 25,
 /** mark an index record as the predefined minimum record */
 MLOG_REC_MIN_MARK = 26,
 /** initialize an ibuf bitmap page */
 MLOG_IBUF_BITMAP_INIT = 27,
#ifdef UNIV_LOG_LSN_DEBUG
 /** Current LSN */
 MLOG_LSN = 28,
#endif /* UNIV_LOG_LSN_DEBUG */
 /** this means that a file page is taken into use and the prior
 contents of the page should be ignored: in recovery we must not
trust the lsn values stored to the file page.
 Note: it's deprecated because it causes crash recovery problem
 in bulk create index, and actually we don't need to reset page
 lsn in recv_recover_page_func() now. */
 MLOG_INIT_FILE_PAGE = 29,
 /** write a string to a page */
 MLOG_WRITE_STRING = 30,
 /** If a single mtr writes several log records, this log
 record ends the sequence of these records */
 MLOG_MULTI_REC_END = 31,
 /** dummy log record used to pad a log block full */
 MLOG_DUMMY_RECORD = 32,
 /** log record about creating an .ibd file, with format */
 MLOG_FILE_CREATE = 33,
 /** rename a tablespace file that starts with (space_id,page_no) */
 MLOG_FILE_RENAME = 34,
 /** delete a tablespace file that starts with (space_id,page_no) */
 MLOG_FILE_DELETE = 35,
 /** mark a compact index record as the predefined minimum record */
 MLOG_COMP_REC_MIN_MARK = 36,
 /** create a compact index page */
 MLOG_COMP_PAGE_CREATE = 37,
 /** compact record insert */
 MLOG_COMP_REC_INSERT_8027 = 38,
 /** mark compact clustered index record deleted */
 MLOG_COMP_REC_CLUST_DELETE_MARK_8027 = 39,
 /** mark compact secondary index record deleted; this log
 record type is redundant, as MLOG_REC_SEC_DELETE_MARK is
 independent of the record format. */
 MLOG_COMP_REC_SEC_DELETE_MARK = 40,
 /** update of a compact record, preserves record field sizes */
 MLOG_COMP_REC_UPDATE_IN_PLACE_8027 = 41,
 /** delete a compact record from a page */
 MLOG_COMP_REC_DELETE_8027 = 42,
/** delete compact record list end on index page */
 MLOG_COMP_LIST_END_DELETE_8027 = 43,
 /*** delete compact record list start on index page */
 MLOG_COMP_LIST_START_DELETE_8027 = 44,
 /** copy compact record list end to a new created index page */
 MLOG_COMP_LIST_END_COPY_CREATED_8027 = 45,
 /** reorganize an index page */
 MLOG_COMP_PAGE_REORGANIZE_8027 = 46,
 /** write the node pointer of a record on a compressed
 non-leaf B-tree page */
 MLOG_ZIP_WRITE_NODE_PTR = 48,
 /** write the BLOB pointer of an externally stored column
 on a compressed page */
 MLOG_ZIP_WRITE_BLOB_PTR = 49,
 /** write to compressed page header */
 MLOG_ZIP_WRITE_HEADER = 50,
 /** compress an index page */
 MLOG_ZIP_PAGE_COMPRESS = 51,
 /** compress an index page without logging it's image */
 MLOG_ZIP_PAGE_COMPRESS_NO_DATA_8027 = 52,
 /** reorganize a compressed page */
 MLOG_ZIP_PAGE_REORGANIZE_8027 = 53,
 /** Create a R-Tree index page */
 MLOG_PAGE_CREATE_RTREE = 57,
 /** create a R-tree compact page */
 MLOG_COMP_PAGE_CREATE_RTREE = 58,
 /** this means that a file page is taken into use.
 We use it to replace MLOG_INIT_FILE_PAGE. */
 MLOG_INIT_FILE_PAGE2 = 59,
 /** Table is being truncated. (Marked only for file-per-table) */
 /* MLOG_TRUNCATE = 60, Disabled for WL6378 */
 /** notify that an index tree is being loaded without writing
redo log about individual pages */
 MLOG_INDEX_LOAD = 61,
 /** log for some persistent dynamic metadata change */
 MLOG_TABLE_DYNAMIC_META = 62,
 /** create a SDI index page */
 MLOG_PAGE_CREATE_SDI = 63,
 /** create a SDI compact page */
 MLOG_COMP_PAGE_CREATE_SDI = 64,
 /** Extend the space */
 MLOG_FILE_EXTEND = 65,
 /** Used in tests of redo log. It must never be used outside unit tests. */
 MLOG_TEST = 66,
 MLOG_REC_INSERT = 67,
 MLOG_REC_CLUST_DELETE_MARK = 68,
 MLOG_REC_DELETE = 69,
 MLOG_REC_UPDATE_IN_PLACE = 70,
 MLOG_LIST_END_COPY_CREATED = 71,
 MLOG_PAGE_REORGANIZE = 72,
 MLOG_ZIP_PAGE_REORGANIZE = 73,
 MLOG_ZIP_PAGE_COMPRESS_NO_DATA = 74,
 MLOG_LIST_END_DELETE = 75,
 MLOG_LIST_START_DELETE = 76,
 /** biggest value (used in assertions) */
 MLOG_BIGGEST_TYPE = MLOG_LIST_START_DELETE
};
// 省略...

 解答问题:

RedoLog的类型根据数据操作的不同场景和对⽇志的优化⽅式有⼏⼗种之多,总体可以分为:
    (1)⽤于数据⻚的⽇志类型,⽐如对数据⻚的修改
    (2)⽤于表空间⽂件的⽇志类型,⽐如对表空间的修改
    (3)提供额外信息的⽇志类型

http://www.kler.cn/a/382756.html

相关文章:

  • WPF 中 NavigationWindow 与 Page 的继承关系解析
  • JavaScript while 循环
  • 太速科技-634-基于3U PXIe的VU3P FMC+数据接口板
  • 【CAP理论:概念、解释与应用】
  • 学习方法该升级了,‌AI时代的弯道超车:【心流学习法】行动与意识合一的巅峰进化
  • 利用pythonstudio写的PDF、图片批量水印生成器,可同时为不同读者生成多组水印
  • 服务器开放了mongodb数据库的外网端口,但是用mongodbCompass还是无法连接。
  • go build --gcflags是什么意思, go build后面还可以接哪些选项
  • 荣耀2025秋招面试题:DiT与传统Stable Diffusion的区别
  • 【笔记】自动驾驶预测与决策规划_Part6_不确定性感知的决策过程
  • Spark 中 RDD 的诞生:原理、操作与分区规则
  • 详解Rust标准库:BTreeSet
  • containerd配置私有仓库registry
  • 【ESP32】ESP-IDF开发 | I2C从机接收i2c_slave_receive函数的BUG导致程序崩溃解决(idf-v5.3.1版本)
  • spring-boot(热部署)
  • 《深度学习》bert自然语言处理框架
  • C++:模拟实现STL的vector
  • 零日漏洞被谷歌的 AI 工具发现
  • 华为HarmonyOS借助AR引擎帮助应用实现虚拟与现实交互的能力6-识别目标形状
  • 【主机游戏】森林之子游戏介绍
  • R语言生物群落(生态)数据统计分析与绘图丨tidyverse数据清洗、多元统计分析、随机森林、回归及混合效应模型、结构方程模型等
  • vue | 自学入门,记录
  • MySQL日期时间函数大全
  • 博客搭建之路:next主题修改侧边栏icon
  • Python画笔案例-096 彩色粒子克隆动画
  • Java多态和继承(上篇)