首页 >> 基础教程

redo log 的写入过程

      InnoDB 的 Redo Log(重做日志)是保证事务 持久性(Durability) 和 崩溃恢复(Crash Recovery) 的核心机制。其写入过程是一个高效且精心设计的流水线,主要涉及内存缓冲和磁盘持久化两个阶段。以下是详细步骤:

Redo Log 写入的核心步骤

  1. 产生 Redo 记录 (During Transaction Execution)

    1. 当事务执行数据修改操作(INSERT、UPDATE、DELETE)时,InnoDB 并不会立即修改磁盘上的数据页。

    2. 它会先在内存中的 Buffer Pool 中找到或加载相应的数据页进行修改(产生“脏页”)。

    3. 同时,InnoDB 会立即为这个物理修改生成一条对应的 Redo Log Record(重做日志记录)。这条记录描述了:“在某个表空间的某个页偏移量(Page+Offset)处,将数据从 X 改为 Y”。

    4. 这些 Redo Log Record 是顺序写入的,并且是物理逻辑日志(物理到页,逻辑到页内的操作)。

  2. 写入 Redo Log Buffer (Memory Buffer)

    1. 生成的 Redo Log Record 首先被写入到内存中的一个特定区域:Redo Log Buffer

    2. Redo Log Buffer 是一个环形缓冲区(Circular Buffer)

    3. 写入 Redo Log Buffer 的速度非常快(内存操作)。

  3. 刷盘到 Redo Log File (Disk Persistence - The Critical Part)

    1. 这是保证持久性的关键步骤。Redo Log Buffer 中的内容需要被刷新(Flush)到磁盘上的 Redo Log Files(通常是 ib_logfile0 和 ib_logfile1)中,才能真正保证即使服务器崩溃,修改也不会丢失。

    2. 刷盘的时机由参数 innodb_flush_log_at_trx_commit 严格控制,这个参数直接决定了事务提交时的持久性级别和性能:

      1. innodb_flush_log_at_trx_commit = 1 (默认值,最安全)

        1. 每次事务提交时,都会执行以下操作:

          1. Write: 将 Redo Log Buffer 中与该事务相关的所有 Redo Log Records 写入到操作系统的文件系统缓存(Page Cache)。

          2. Fsync: 立即调用 fsync() 系统调用,强制将文件系统缓存中的 Redo Log 数据刷到物理磁盘上。

        2. 效果:确保事务提交后,其修改绝对持久化到磁盘。崩溃后数据不会丢失。性能开销最大(因为每次提交都要等磁盘 I/O)。

      2. innodb_flush_log_at_trx_commit = 2 (折衷方案)

        1. 每次事务提交时

          1. Write: 将 Redo Log Buffer 中与该事务相关的所有 Redo Log Records 写入到操作系统的文件系统缓存(Page Cache)。

        2. 不执行 fsync()。操作系统会每秒(大约) 自动调用一次 fsync() 将文件系统缓存中的数据刷到物理磁盘。

        3. 效果:如果 MySQL 进程崩溃(Crash),由于日志在操作系统的 Page Cache 里,重启后还能恢复,数据不会丢失。如果操作系统或机器宕机(Power Failure),则可能丢失最后约 1 秒内提交的事务(因为 Page Cache 中的数据没来得及刷盘)。性能比 =1 好很多(不需要等磁盘 I/O)

      3. innodb_flush_log_at_trx_commit = 0 (最快,最不安全)

        1. 每秒进行一次刷盘操作:

          1. Write: 将 Redo Log Buffer 中的内容写入到操作系统的文件系统缓存(Page Cache)。

          2. Fsync: 调用 fsync() 将 Page Cache 中的数据刷到物理磁盘。

        2. 事务提交时不做任何保证的刷盘操作

        3. 效果:如果 MySQL 进程崩溃操作系统/机器宕机,都可能丢失最多约 1 秒内提交的所有事务。性能最好(事务提交几乎无等待)。

    3. 其他刷盘触发点 (Regardless of innodb_flush_log_at_trx_commit)

      1. Redo Log Buffer 空间不足时:当 Buffer 使用超过一定比例(约 3/4),后台线程会自动触发刷盘。

      2. 后台线程定期刷盘:有一个专门的 InnoDB 后台线程(log_writer / log_flusher)大约每秒会检查并尝试刷盘一次。

      3. Checkpoint 推进时:需要保证 Checkpoint LSN 之前的 Redo Log 已被安全覆盖。

      4. Binary Log 组提交 (Group Commit) 协调时:在 Prepare 阶段(两阶段提交的第一步),即使 innodb_flush_log_at_trx_commit=0,也会强制将 Redo Log 刷盘(fsync),以保证 Binlog 和 Redo Log 的一致性基础。


  4. 写入 Redo Log Files (物理结构)

    1. Redo Log Files 通常是两个(或更多)固定大小的文件(如 ib_logfile0ib_logfile1),以循环写入(Circular Writing) 的方式工作。

    2. InnoDB 维护一个指针 Write Position (LSN),指示下一个 Redo Record 应该写入文件中的哪个位置。

    3. 当写满最后一个文件时,会回绕(Wrap Around) 到第一个文件的开头继续写。

    4. 为了保证数据安全,被覆盖的 Redo Log 区域必须满足一个条件:这个区域对应的脏页修改已经刷新到了磁盘上的数据文件(.ibd)。这个确保安全覆盖的点称为 Checkpoint。Checkpoint LSN 之前的 Redo Log 可以被安全覆盖。


关键概念:LSN (Log Sequence Number)

  • LSN 是什么? 一个单调递增的 64 位整数,代表自系统启动以来产生的 Redo Log 总量(字节数)。

  • 作用

    • 唯一标识:每个 Redo Log Record、每个数据页(记录 page_lsn)、每个 Checkpoint 都关联一个 LSN。

    • 顺序控制:决定 Redo Log 的写入顺序和恢复时的应用顺序。

    • 恢复起点:崩溃恢复时,从 Checkpoint LSN 开始扫描和应用后续的 Redo Log。

    • 进度追踪:跟踪 Buffer Pool 中脏页的刷新进度(oldest_modification LSN)。

总结:Redo Log 写入流程的本质

  1. 生成日志:数据修改 => 生成 Redo Log Record (物理逻辑)。

  2. 缓冲加速:先写入内存中的 Redo Log Buffer (顺序, 快速)。

  3. 持久化关键

    • 根据 innodb_flush_log_at_trx_commit 设置,在事务提交时或特定时间点。

    • 执行 write (到 OS Page Cache) 和 fsync (到物理磁盘)。

    • 确保 fsync 才能真正保证崩溃后不丢数据。

  4. 循环写入:顺序写入固定大小的 Redo Log Files,循环覆盖(受 Checkpoint 保护)。

  5. LSN 贯穿始终:LSN 是整个流程的全局逻辑时钟,用于追踪、恢复和一致性控制。



最新文章
mysql分页问题2025-08-04
千万数据先insert和先建索引哪个快2025-08-04
MySQL 中大小表关联查询如何优化2025-08-04
sql技巧-每个班年龄排前两名的人2025-08-03
MySQL 导致 cpu 飙升的话,要怎么处理呢?2025-07-29
MySQL 中为千万级大表添加字段2025-07-29
mysql中百万级别以上的数据如何删除2025-07-29
分库分表带来的问题2025-07-29
mysql中常用的分库分表中间件有哪些2025-07-29
mysql不停机扩容2025-07-29
备案号:蜀ICP备2023042032号-1