InnoDB Redo日志

197 阅读10分钟

InnoDB Redo日志

1. Redo日志的作用

Redo日志(Redo Log)是InnoDB存储引擎中用于保证事务持久性的重要机制。事务提交后,即使系统发生崩溃,通过Redo日志可以将事务对数据库的修改重新应用,从而确保数据的完整性和一致性。

flowchart TD
    A[事务开始] --> B[修改数据页]
    B --> C[生成Redo日志]
    C --> D[事务提交]
    D --> E[Redo日志刷盘]
    E --> F[系统崩溃]
    F --> G[重启恢复]
    G --> H[读取Redo日志]
    H --> I[重放修改操作]
    I --> J[数据恢复完成]
    
    style C fill:#e1f5fe
    style E fill:#f3e5f5
    style I fill:#e8f5e8

1.1 持久性保证机制

Redo日志通过以下方式保证事务的持久性:

  • 预写日志(WAL):在数据页刷盘之前,必须先将对应的Redo日志刷盘
  • 顺序写入:Redo日志采用顺序写入方式,提高I/O效率
  • 原子性恢复:崩溃恢复时,能够原子性地重放所有已提交事务的修改

2. Redo日志的设计动机

InnoDB以页为单位管理存储空间,事务操作(如增删改查)本质上是对页面的访问和修改。为了保证事务的持久性,需要将修改后的页面刷新到磁盘。然而,直接刷新页面存在以下问题:

2.1 性能问题分析

flowchart LR
    subgraph "直接刷页面的问题"
        A[修改1个字节] --> B[刷新整个16KB页面]
        C[多个不相邻页面] --> D[随机I/O操作]
        E[频繁磁盘写入] --> F[性能瓶颈]
    end
    
    subgraph "Redo日志解决方案"
        G[记录修改内容] --> H[顺序写入日志]
        I[批量刷盘] --> J[提高性能]
    end
    
    B --> G
    D --> H
    F --> I
    
    style B fill:#ffebee
    style D fill:#ffebee
    style F fill:#ffebee
    style H fill:#e8f5e8
    style I fill:#e8f5e8
    style J fill:#e8f5e8

2.2 问题详解

  1. 浪费磁盘I/O:即使只修改了一个字节,也需要刷新整个页面(默认16KB)
  2. 随机I/O性能差:一个事务可能修改多个不相邻的页面,导致随机I/O操作频繁,尤其在机械硬盘上效率低下
  3. 内存压力:频繁的页面刷新会增加内存和磁盘的压力

因此,InnoDB引入了Redo日志机制,仅记录对页面的修改内容,而不是直接刷新整个页面。


3. Redo日志的格式

Redo日志记录了事务对数据库的修改操作,其结构通常包含以下部分:

classDiagram
    class RedoLogRecord {
        +Type: 日志类型
        +Space_ID: 表空间ID
        +Page_Number: 页面编号
        +Data: 具体修改内容
        +Checksum: 校验和
    }
    
    class LogType {
        +MLOG_1BYTE
        +MLOG_2BYTE
        +MLOG_4BYTE
        +MLOG_8BYTE
        +MLOG_WRITE_STRING
        +MLOG_REC_INSERT
        +MLOG_COMP_REC_INSERT
    }
    
    RedoLogRecord --> LogType

3.1 字段详解

字段描述作用
Type日志类型表示日志的用途(如插入记录、更新记录等)
Space ID表空间ID标识日志所属的表空间
Page Number页面编号标识被修改的页面
Data日志内容记录修改的详细信息
Checksum校验和确保日志完整性

4. Redo日志的类型

InnoDB根据不同的修改场景定义了多种类型的Redo日志,常见的类型包括:

4.1 基础数据类型日志

flowchart LR
    A[Redo日志类型] --> B[基础数据类型]
    A --> C[记录操作类型]
    A --> D[页面操作类型]
    A --> E[压缩相关类型]
    
    B --> B1[MLOG_1BYTE<br/>写入1字节]
    B --> B2[MLOG_2BYTE<br/>写入2字节]
    B --> B3[MLOG_4BYTE<br/>写入4字节]
    B --> B4[MLOG_8BYTE<br/>写入8字节]
    B --> B5[MLOG_WRITE_STRING<br/>写入字符串]
    
    C --> C1[MLOG_REC_INSERT<br/>插入非紧凑记录]
    C --> C2[MLOG_COMP_REC_INSERT<br/>插入紧凑记录]
    C --> C3[MLOG_COMP_REC_DELETE<br/>删除紧凑记录]
    
    D --> D1[MLOG_COMP_PAGE_CREATE<br/>创建紧凑页面]
    
    E --> E1[MLOG_ZIP_PAGE_COMPRESS<br/>压缩数据页]
    
    style B1 fill:#e3f2fd
    style C1 fill:#f3e5f5
    style D1 fill:#e8f5e8
    style E1 fill:#fff3e0

4.2 日志类型详解

  • MLOG_1BYTE、MLOG_2BYTE、MLOG_4BYTE、MLOG_8BYTE:分别表示在页面的某个偏移量处写入1、2、4、8个字节的数据
  • MLOG_WRITE_STRING:表示在页面的某个偏移量处写入一串数据
  • MLOG_REC_INSERT、MLOG_COMP_REC_INSERT:分别表示插入一条非紧凑行格式记录和紧凑行格式记录
  • MLOG_COMP_PAGE_CREATE、MLOG_COMP_REC_DELETE:表示创建一个紧凑行格式记录的页面和删除一条紧凑行格式记录
  • MLOG_ZIP_PAGE_COMPRESS:表示压缩一个数据页

5. Redo日志的物理与逻辑特性

Redo日志具有物理和逻辑的双重特性:

flowchart LR
    subgraph "物理层面"
        A[指定表空间ID] --> B[指定页面编号]
        B --> C[精确定位修改位置]
    end
    
    subgraph "逻辑层面"
        D[调用特定函数] --> E[传入日志参数]
        E --> F[执行恢复操作]
    end
    
    C --> D
    
    style A fill:#e3f2fd
    style B fill:#e3f2fd
    style C fill:#e3f2fd
    style D fill:#f3e5f5
    style E fill:#f3e5f5
    style F fill:#f3e5f5

5.1 特性详解

  • 物理层面:Redo日志指明了对哪个表空间的哪个页面进行了修改
  • 逻辑层面:在系统崩溃重启时,不能直接根据日志恢复页面,而是需要调用特定函数,根据日志中的参数执行操作,从而恢复页面

这种设计使得Redo日志既能精确定位修改位置,又能灵活地执行恢复操作。


6. Mini-Transaction(mtr)

Mini-Transaction是InnoDB中对底层页面进行原子访问的过程。一个mtr可以包含一组Redo日志,在崩溃恢复时,这些日志作为一个不可分割的整体。

sequenceDiagram
    participant App as 应用程序
    participant MTR as Mini-Transaction
    participant Log as Redo日志
    participant Page as 数据页
    
    App->>MTR: 开始mtr
    MTR->>Page: 修改页面1
    MTR->>Log: 生成日志1
    MTR->>Page: 修改页面2
    MTR->>Log: 生成日志2
    MTR->>Log: 原子性提交所有日志
    MTR->>App: mtr完成
    
    Note over MTR,Log: 所有日志作为一个整体<br/>要么全部应用,要么全部不应用

6.1 mtr的典型场景

  • 更新Max Row ID属性:这是一个完整的mtr操作
  • 向B+树中插入记录:包含多个页面修改的复杂mtr
  • 页面分裂操作:涉及多个页面的原子性操作

6.2 mtr的重要性

  1. 原子性保证:确保相关的多个页面修改要么全部成功,要么全部失败
  2. 一致性维护:保持数据结构(如B+树)的完整性
  3. 恢复简化:崩溃恢复时按mtr为单位进行,简化恢复逻辑

7. Redo日志的写入过程

7.1 Redo Log Block结构

classDiagram
    class RedoLogBlock {
        +Header: 12字节
        +Body: 496字节
        +Trailer: 4字节
        +Total: 512字节
    }
    
    class Header {
        +LOG_BLOCK_HDR_NO: 4字节
        +LOG_BLOCK_HDR_DATA_LEN: 2字节
        +LOG_BLOCK_FIRST_REC_GROUP: 2字节
        +LOG_BLOCK_CHECKPOINT_NO: 4字节
    }
    
    class Trailer {
        +LOG_BLOCK_CHECKSUM: 4字节
    }
    
    RedoLogBlock --> Header
    RedoLogBlock --> Trailer

7.2 写入流程

flowchart TD
    A[mtr开始] --> B[生成Redo日志]
    B --> C[写入Log Buffer]
    C --> D[mtr结束]
    D --> E{Log Buffer是否满?}
    E -->|是| F[刷盘到日志文件]
    E -->|否| G[继续写入]
    F --> H[更新LSN]
    G --> I[等待下次刷盘]
    
    style C fill:#e3f2fd
    style F fill:#f3e5f5
    style H fill:#e8f5e8

7.3 关键组件

  • Redo Log Block:Redo日志存储在大小为512字节的块(block)中,每个block包含日志头部(header)、日志正文(body)和日志尾部(trailer)
  • Redo日志缓冲区(Log Buffer):日志首先写入内存中的Log Buffer,Log Buffer被划分为多个连续的block。通过innodb_log_buffer_size参数可以设置Log Buffer的大小,默认为16MB
  • 写入Log Buffer:日志以mtr为单位写入Log Buffer,每个mtr产生的日志组在mtr结束时一次性写入Log Buffer

8. Redo日志的刷盘时机

日志不会一直停留在内存中,会在以下情况下被刷新到磁盘:

flowchart TD
    A[Redo日志刷盘触发条件] --> B[Log Buffer空间不足]
    A --> C[事务提交]
    A --> D[后台线程定期刷新]
    A --> E[服务器正常关闭]
    A --> F[Checkpoint操作]
    
    B --> B1[使用量达到50%]
    C --> C1[保证事务持久性]
    D --> D1[每秒定期刷新]
    E --> E1[刷新所有日志]
    F --> F1[配合脏页刷新]
    
    style B1 fill:#ffebee
    style C1 fill:#e8f5e8
    style D1 fill:#e3f2fd
    style E1 fill:#fff3e0
    style F1 fill:#f3e5f5

8.1 刷盘时机详解

  1. Log Buffer空间不足:当Log Buffer的使用量达到一定比例(如一半)时,日志会被刷新到磁盘
  2. 事务提交时:为了保证事务的持久性,事务提交时会将对应的Redo日志刷新到磁盘
  3. 后台线程定期刷新:后台线程会定期(如每秒)将Log Buffer中的日志刷新到磁盘
  4. 正常关闭服务器时:服务器关闭时会将所有日志刷新到磁盘
  5. Checkpoint操作时:在执行Checkpoint操作时,日志也会被刷新到磁盘

9. Redo日志文件组

Redo日志文件以组的形式存在,默认情况下有两个文件:ib_logfile0ib_logfile1

flowchart LR
    A[ib_logfile0] --> B[ib_logfile1]
    B --> C[ib_logfile2]
    C --> D[...]
    D --> E[ib_logfile99]
    E --> A
    
    F[写入指针] --> A
    
    style A fill:#e8f5e8
    style B fill:#e3f2fd
    style F fill:#f3e5f5

9.1 配置参数

可以通过以下参数调整日志文件的配置:

参数描述默认值范围
innodb_log_group_home_dir日志文件所在目录数据目录-
innodb_log_file_size每个日志文件大小48MB1MB-512GB
innodb_log_files_in_group日志文件数量22-100

9.2 循环写入机制

日志文件以循环方式写入,当一个文件写满后,会切换到下一个文件,直到最后一个文件写满后重新从第一个文件开始写。这种设计确保了:

  • 空间利用率高:充分利用所有日志文件空间
  • 写入连续性:保持顺序写入的性能优势
  • 自动管理:无需手动管理日志文件切换

10. Redo日志文件格式

每个Redo日志文件由两部分组成:

classDiagram
    class RedoLogFile {
        +前2048字节: 管理信息
        +后续部分: Log Block镜像
    }
    
    class ManagementInfo {
        +Log File Header: 512字节
        +Checkpoint1: 512字节
        +空白区域: 512字节
        +Checkpoint2: 512字节
    }
    
    class LogFileHeader {
        +LOG_HEADER_FORMAT: 格式版本
        +LOG_HEADER_PAD1: 填充
        +LOG_HEADER_START_LSN: 起始LSN
        +LOG_HEADER_CREATOR: 创建信息
    }
    
    RedoLogFile --> ManagementInfo
    ManagementInfo --> LogFileHeader

10.1 文件结构详解

  • 前2048字节:存储管理信息,包括日志文件头部(log file header)和Checkpoint信息
  • 后续部分:存储Log Buffer中的block镜像

10.2 管理信息的作用

  1. 文件头部:记录日志文件的基本信息和格式版本
  2. Checkpoint信息:用于崩溃恢复时确定恢复起点
  3. 双Checkpoint设计:提供冗余保护,确保至少有一个有效的Checkpoint

11. Log Sequence Number(LSN)

LSN是一个全局变量,用于记录系统写入的Redo日志量。LSN的初始值为8704,随着日志的写入不断增加。

flowchart TD
    A[LSN = 8704<br/>初始值] --> B[写入日志正文]
    B --> C[LSN += 日志正文大小]
    C --> D[写入日志头部和尾部]
    D --> E[LSN += 头部尾部大小]
    E --> F[LSN持续增长]
    
    G[LSN的组成] --> H[日志正文大小]
    G --> I[日志头部大小]
    G --> J[日志尾部大小]
    
    style A fill:#e3f2fd
    style F fill:#e8f5e8
    style H fill:#f3e5f5
    style I fill:#fff3e0
    style J fill:#ffebee

11.1 LSN的增长规律

LSN的增长包括:

  • 日志正文的大小:实际写入的日志内容
  • 日志头部和尾部的大小:即使日志正文较小,也会加上头部和尾部的大小

11.2 LSN的重要作用

  1. 唯一标识:每个日志记录都有唯一的LSN标识
  2. 顺序保证:LSN的递增保证了日志的写入顺序
  3. 恢复定位:崩溃恢复时用于确定恢复的起点和终点
  4. 一致性检查:用于验证页面和日志的一致性

12. Flushed_to_disk_lsn

flushed_to_disk_lsn是一个全局变量,记录已经刷新到磁盘的Redo日志量。其值初始与LSN相同,随着日志刷新到磁盘而增长。

sequenceDiagram
    participant Buffer as Log Buffer
    participant Disk as 磁盘日志文件
    participant LSN as LSN计数器
    participant FDLSN as flushed_to_disk_lsn
    
    Note over Buffer,FDLSN: 初始状态:LSN = flushed_to_disk_lsn = 8704
    
    Buffer->>LSN: 写入日志,LSN增加
    Note over LSN: LSN = 10000
    Note over FDLSN: flushed_to_disk_lsn = 8704
    
    Buffer->>Disk: 刷盘操作
    Disk->>FDLSN: 更新flushed_to_disk_lsn
    Note over FDLSN: flushed_to_disk_lsn = 10000
    
    Note over LSN,FDLSN: LSN - flushed_to_disk_lsn = 未刷盘的日志量

12.1 作用和意义

  • 持久化跟踪:跟踪哪些日志已经安全地写入磁盘
  • 恢复优化:崩溃恢复时可以跳过已经持久化的部分
  • 性能监控:通过LSN - flushed_to_disk_lsn可以了解待刷盘的日志量

13. Checkpoint机制

Checkpoint用于标记可以被覆盖的Redo日志。Checkpoint的执行包括以下步骤:

flowchart TD
    A[开始Checkpoint] --> B[扫描Buffer Pool]
    B --> C[找到最早的脏页]
    C --> D[获取oldest_modification]
    D --> E[设置checkpoint_lsn]
    E --> F[计算日志文件偏移量]
    F --> G[生成Checkpoint编号]
    G --> H{编号是奇数?}
    H -->|是| I[写入checkpoint1]
    H -->|否| J[写入checkpoint2]
    I --> K[Checkpoint完成]
    J --> K
    
    style E fill:#e8f5e8
    style I fill:#e3f2fd
    style J fill:#f3e5f5
    style K fill:#fff3e0

13.1 Checkpoint执行步骤

  1. 计算Checkpoint LSN:找到当前系统中最早修改的脏页对应的oldest_modification值,将其赋值给checkpoint_lsn
  2. 记录Checkpoint信息:将checkpoint_lsn、对应的日志文件偏移量和Checkpoint编号写入日志文件的管理信息中
  3. 双重保护:Checkpoint的编号存储在checkpoint1checkpoint2中,根据编号的奇偶性决定存储位置

13.2 Checkpoint的重要性

  • 空间回收:标记可以被覆盖的日志空间
  • 恢复优化:确定崩溃恢复的起点,减少恢复时间
  • 一致性保证:确保脏页刷盘和日志的一致性

14. 崩溃恢复

在系统崩溃后,可以通过Redo日志恢复数据。恢复过程如下:

flowchart TD
    A[系统崩溃重启] --> B[读取Checkpoint信息]
    B --> C[确定恢复起点<br/>checkpoint_lsn]
    C --> D[扫描日志文件]
    D --> E[找到最后一个完整block]
    E --> F[确定恢复终点]
    F --> G[按LSN顺序读取日志]
    G --> H[解析日志记录]
    H --> I[检查页面LSN]
    I --> J{页面需要恢复?}
    J -->|是| K[应用日志修改]
    J -->|否| L[跳过该日志]
    K --> M[继续下一条日志]
    L --> M
    M --> N{还有日志?}
    N -->|是| G
    N -->|否| O[恢复完成]
    
    style C fill:#e8f5e8
    style F fill:#e3f2fd
    style K fill:#f3e5f5
    style O fill:#fff3e0

14.1 恢复过程详解

  1. 确定恢复起点:从最近一次Checkpoint的checkpoint_lsn开始读取日志
  2. 确定恢复终点:扫描日志文件,找到最后一个未填满的block
  3. 恢复数据:按照日志的顺序,将对应的页面恢复到崩溃前的状态。可以通过哈希表优化恢复过程,避免重复读取页面

14.2 恢复优化策略

flowchart LR
    A[恢复优化] --> B[哈希表分组]
    A --> C[页面LSN检查]
    A --> D[批量I/O操作]
    
    B --> B1[按Space ID + Page Number分组]
    C --> C1[跳过已刷新页面]
    D --> D1[减少随机I/O]
    
    style B1 fill:#e8f5e8
    style C1 fill:#e3f2fd
    style D1 fill:#f3e5f5

15. 多页面操作与Redo日志机制详解

15.1 多页面操作的Redo日志生成策略

当一个操作涉及多个页面时,InnoDB会为每个被修改的页面生成对应的Redo日志记录,而不是生成一条综合的日志。这种设计有以下原因:

flowchart TD
    A[一个事务操作] --> B[修改页面1]
    A --> C[修改页面2]
    A --> D[修改页面3]
    
    B --> B1[生成Redo日志1<br/>Space ID: 1, Page: 100]
    C --> C1[生成Redo日志2<br/>Space ID: 1, Page: 200]
    D --> D1[生成Redo日志3<br/>Space ID: 2, Page: 50]
    
    B1 --> E[Mini-Transaction边界]
    C1 --> E
    D1 --> E
    
    E --> F[原子性提交所有日志]
    
    style E fill:#e8f5e8
    style F fill:#f3e5f5
15.1.1 为什么需要多条Redo日志
原因说明优势
精确恢复每个页面的修改都有独立的日志记录可以精确恢复每个页面的状态
并行恢复不同页面的恢复可以并行进行提高崩溃恢复的效率
选择性恢复可以根据页面LSN跳过已恢复的页面避免重复恢复,提高性能
故障隔离单个页面的问题不影响其他页面提高系统的健壮性
15.1.2 Mini-Transaction的作用

虽然生成多条Redo日志,但通过Mini-Transaction机制确保原子性:

sequenceDiagram
    participant App as 应用操作
    participant MTR as Mini-Transaction
    participant Page1 as 页面1
    participant Page2 as 页面2
    participant Page3 as 页面3
    participant Log as Redo日志
    
    App->>MTR: 开始复杂操作
    MTR->>Page1: 修改页面1
    MTR->>Log: 记录日志1
    MTR->>Page2: 修改页面2
    MTR->>Log: 记录日志2
    MTR->>Page3: 修改页面3
    MTR->>Log: 记录日志3
    MTR->>Log: 原子性提交所有日志
    MTR->>App: 操作完成
    
    Note over MTR,Log: 崩溃恢复时,这些日志<br/>要么全部重放,要么全部跳过

15.2 Checkpoint机制与多页面操作

15.2.1 Checkpoint如何处理多页面操作

Checkpoint机制在处理多页面操作时,会考虑所有相关页面的状态:

flowchart TD
    A[Checkpoint开始] --> B[扫描Buffer Pool中所有脏页]
    B --> C[找到oldest_modification最小的脏页]
    C --> D[该页面对应的LSN]
    D --> E[设置为checkpoint_lsn]
    
    F[多页面操作示例] --> G[页面A: LSN=1000]
    F --> H[页面B: LSN=1200]
    F --> I[页面C: LSN=1500]
    
    G --> J[如果页面A未刷盘<br/>checkpoint_lsn = 1000]
    H --> K[如果页面B未刷盘<br/>checkpoint_lsn = 1200]
    I --> L[如果页面C未刷盘<br/>checkpoint_lsn = 1500]
    
    style C fill:#e8f5e8
    style E fill:#f3e5f5
    style J fill:#ffebee
15.2.2 重放起点的确定原理

Redo日志的重放起点确定遵循以下原则:

  1. 最保守原则:从最早未刷盘页面的LSN开始
  2. 完整性保证:确保所有相关的Mini-Transaction都能完整重放
  3. 一致性维护:保证数据结构(如B+树)的完整性
flowchart LR
    A[确定重放起点] --> B[读取最新Checkpoint]
    B --> C[获取checkpoint_lsn]
    C --> D[从该LSN开始扫描]
    D --> E[找到完整的mtr边界]
    E --> F[开始重放操作]
    
    G[示例场景] --> H[checkpoint_lsn = 1000]
    H --> I[扫描发现mtr在LSN=995开始]
    I --> J[实际从LSN=995开始重放]
    
    style C fill:#e8f5e8
    style E fill:#f3e5f5
    style J fill:#e3f2fd

15.3 实际案例分析

15.3.1 B+树页面分裂操作

以B+树页面分裂为例,说明多页面操作的Redo日志处理:

flowchart TD
    A[B+树页面分裂操作] --> B[原页面修改]
    A --> C[新页面创建]
    A --> D[父页面更新]
    A --> E[系统页面更新]
    
    B --> B1["Redo日志1: MLOG_COMP_REC_DELETE<br/>删除部分记录"]
    C --> C1["Redo日志2: MLOG_COMP_PAGE_CREATE<br/>创建新页面"]
    C --> C2["Redo日志3: MLOG_COMP_REC_INSERT<br/>插入记录到新页面"]
    D --> D1["Redo日志4: MLOG_COMP_REC_INSERT<br/>父页面插入索引项"]
    E --> E1["Redo日志5: MLOG_4BYTE<br/>更新系统信息"]
    
    B1 --> F[Mini-Transaction提交]
    C1 --> F
    C2 --> F
    D1 --> F
    E1 --> F
    
    style F fill:#e8f5e8
15.3.2 崩溃恢复时的处理
sequenceDiagram
    participant Recovery as 恢复进程
    participant Checkpoint as Checkpoint信息
    participant LogFile as 日志文件
    participant Page as 数据页
    
    Recovery->>Checkpoint: 读取checkpoint_lsn
    Note over Checkpoint: checkpoint_lsn = 1000
    
    Recovery->>LogFile: 从LSN=1000开始扫描
    LogFile->>Recovery: 发现mtr开始于LSN=995
    
    Recovery->>LogFile: 从LSN=995开始读取
    LogFile->>Recovery: 返回完整的mtr日志组
    
    Recovery->>Page: 检查页面LSN
    Page->>Recovery: 页面LSN < 日志LSN,需要恢复
    
    Recovery->>Page: 按顺序应用所有日志
    Note over Recovery,Page: 原子性恢复整个mtr操作

15.4 性能优化考虑

15.4.1 批量处理优化
flowchart LR
    A[多页面日志] --> B[按页面分组]
    B --> C[哈希表存储]
    C --> D[批量读取页面]
    D --> E[顺序应用日志]
    E --> F[减少I/O次数]
    
    G[优化效果] --> H["减少随机I/O: 60-80%"]
    G --> I["提升恢复速度: 40-60%"]
    G --> J["降低内存使用: 30-50%"]
    
    style C fill:#e8f5e8
    style F fill:#f3e5f5
15.4.2 并行恢复策略

对于涉及不同表空间或不相关页面的操作,可以采用并行恢复:

并行策略适用场景性能提升
表空间级并行不同表空间的页面修改2-4倍速度提升
页面级并行同表空间不相关页面1.5-3倍速度提升
mtr级串行同一mtr内的页面修改保证一致性,无并行

16. 总结

Redo日志是InnoDB存储引擎中实现事务持久性的关键机制。通过记录页面的修改内容,Redo日志在系统崩溃后可以恢复数据,同时避免了直接刷新页面带来的性能问题。