InnoDB REDO LOG 详解:从原理到实现(基于 MySQL 8.0)
在现代关系型数据库系统中事务的持久性Durability是 ACID 特性的关键一环。为了在系统崩溃后仍能恢复数据一致性InnoDB 引擎引入了REDO LOG重做日志机制。本文将深入剖析 REDO LOG 的作用、设计思想、组织结构、写入流程以及清理策略帮助读者全面理解其在 InnoDB 中的核心地位。 目录为什么需要 REDO LOGREDO LOG 的设计目标与 Physiological LoggingREDO LOG 的内容分类REDO LOG 的三层组织结构高效写入机制MySQL 8.0 优化REDO LOG 的安全清理Checkpoint 机制总结延伸阅读1️⃣ 为什么需要 REDO LOGInnoDB 采用Buffer Pool缓存数据页以提升性能对磁盘的修改往往滞后于内存。若此时发生崩溃未刷盘的脏页将丢失破坏数据一致性。 WAL 机制为解决此问题InnoDB 引入WALWrite-Ahead Logging机制┌─────────────────────────────────────────────────┐ │ 在修改 Page 前先将变更记录写入 REDO LOG │ │ 并确保 REDO 先于 Page 落盘 │ └─────────────────────────────────────────────────┘系统重启时通过重放 REDO LOG可将 Page 恢复至崩溃前状态从而保证事务的持久性。2️⃣ REDO LOG 的设计目标与 Physiological Logging理想的 REDO LOG 需满足以下要求设计目标说明数据量小减少 I/O 开销提升吞吐幂等性重放多次结果一致避免重复应用基于 Page便于并行恢复 传统日志对比日志类型优点缺点Logical Logging体积小恢复慢Physical Logging恢复快日志量大 InnoDB 的解决方案Physiological LoggingInnoDB 采用Physiological Logging——以 Page 为单位在 Page 内部使用逻辑方式记录变更。示例MLOG_REC_UPDATE_IN_PLACE(Page ID, Record Offset, (Field 1, Value 1), ..., (Field i, Value i))这种方式兼顾了日志体积与恢复效率但也带来两个挑战⚠️ 挑战一Page 状态必须正确由于 InnoDB Page默认 16KB大于文件系统原子写单位4KB可能出现半写页。解决方案InnoDB 引入Double Write Buffer机制确保总能找到一个完整有效的 Page。⚠️ 挑战二保证重放幂等InnoDB 为每条 REDO 分配全局唯一递增的LSNLog Sequence Number。机制Page 在修改时会记录对应 REDO 的 LSN存于FIL_PAGE_LSN字段恢复时若 Page 的 LSN ≥ REDO 的 LSN则跳过该 REDO实现幂等重放3️⃣ REDO LOG 的内容分类MySQL 8.0 中定义了65 种 REDO 类型可分为三大类 1作用于 Page 的 REDO占绝大多数子类型说明示例Index Page索引页操作MLOG_REC_INSERT,MLOG_REC_UPDATE_IN_PLACE,MLOG_REC_DELETEUndo PageUndo 页操作-R-tree PageR树页操作-示例MLOG_REC_UPDATE_IN_PLACE结构┌─────────────────────────────────────────────────────────┐ │ Header (固定) │ ├─────────────────────────────────────────────────────────┤ │ Type │ Space ID │ Page Number │ ├─────────────────────────────────────────────────────────┤ │ Body (可变) │ ├─────────────────────────────────────────────────────────┤ │ Record Offset │ Update Field Count │ (Field Number, │ │ │ │ Data Length, │ │ │ │ Data) × N │ └─────────────────────────────────────────────────────────┘ 2作用于 Space 的 REDO用于文件级操作类型说明MLOG_FILE_CREATE文件创建MLOG_FILE_DELETE文件删除MLOG_FILE_RENAME文件重命名特点此类 REDO 在操作成功后才记录恢复时主要用于校验文件状态Page Number 固定为 0️ 3Logic 类型 REDO不修改数据仅提供控制信息。类型说明MLOG_MULTI_REC_END标识一个原子操作mtr的结束4️⃣ REDO LOG 的三层组织结构REDO LOG 从逻辑到物理分为三层 1逻辑层Logical REDO由连续的 REDO 记录组成使用全局递增偏移snsequence number标识位置log_sys.sn维护当前最大 sn 2物理层Log Block磁盘以Block为单位读写512B每个 Block 结构┌──────────────────────────────────────────────────────┐ │ Block Header (12 bytes) │ ├──────────────┬──────────────┬──────────────┬─────────┤ │ Flush Flag │ Data Length │ First Record │ Check- │ │ Block Num │ (2B) │ Offset (2B) │ point │ │ (4B) │ │ │ Num (4B)│ ├──────────────────────────────────────────────────────┤ │ Data Area (498 bytes) - Logical REDO │ ├──────────────────────────────────────────────────────┤ │ Block Trailer (4 bytes) - Checksum │ └──────────────────────────────────────────────────────┘跨 Block 存储由于 REDO 长度不定可能跨 Block 存储。 LSN 与 sn 的换算constexprinlinelsn_tlog_translate_sn_to_lsn(lsn_t sn){return(sn/LOG_BLOCK_DATA_SIZE*OS_FILE_LOG_BLOCK_SIZEsn%LOG_BLOCK_DATA_SIZELOG_BLOCK_HDR_SIZE);} 3文件层Redo Files文件命名ib_logfile0,ib_logfile1, …循环使用由innodb_log_files_in_group控制数量文件结构┌─────────────────────────────────────────────────────┐ │ Block 0: Header Block │ │ - Format (4B) │ │ - Start LSN (8B) │ │ - Creator (32B) │ ├─────────────────────────────────────────────────────┤ │ Block 1-3: Checkpoint Blocks (ib_logfile0 only) │ ├─────────────────────────────────────────────────────┤ │ Block 4: Log Data Blocks │ └─────────────────────────────────────────────────────┘LSN 到文件 offset 的映射constautoreal_offsetlog.current_file_real_offset(lsn-log.current_file_lsn);5️⃣ 高效写入机制MySQL 8.0 优化REDO 写入是事务提交的关键路径。MySQL 8.0 引入无锁并发写入架构 写入流程图REDO 生成Log BufferPage Cache磁盘唤醒用户线程 详细步骤1REDO 生成mtrmini-transaction原子操作的所有 REDO 先写入 mtr 的本地m_logmtr_commit()时批量拷贝到 Log Buffer2写入 Log Buffer无锁分配/* Reserve space in sequence of data bytes: */constsn_t start_snlog.sn.fetch_add(len);多个 mtr 并发调用log_buffer_reserve()通过fetch_add原子获取独享空间避免锁竞争3写入 Page Cachelog_writer link_buflink_buf 工作原理┌─────────────────────────────────────────────────────────┐ │ link_buf (循环数组) │ │ [LSN % size] → REDO 长度 │ │ │ │ log_writer 扫描找到连续区域 → 调用 pwrite 写入 OS Cache │ └─────────────────────────────────────────────────────────┘关键变量write_lsn已写入 Page Cache 的位置buf_ready_for_write_lsnLog Buffer 中连续日志的末尾current_lsn已分配的最大 LSN4刷盘log_flusherlog_writer通知log_flusherlog_flusher调用fsync确保持久化5唤醒用户线程优化策略条件变量按 Block 分片减少竞争专用线程负责唤醒log_write_notifier/log_flush_notifier⚙️ 安全级别配置配置值说明安全性性能innodb_flush_log_at_trx_commit1REDO 刷盘后提交⭐⭐⭐⭐⭐⭐⭐⭐2仅写入 OS Cache 即提交⭐⭐⭐⭐⭐⭐⭐⭐6️⃣ REDO LOG 的安全清理Checkpoint 机制REDO 文件空间有限需定期清理已无需保留的日志。InnoDB 通过Checkpoint标记可回收位置。 Checkpoint LSN 的确定需确保 Checkpoint 之前的所有脏页均已刷盘/* LWM lsn for unflushed dirty pages in Buffer Pool */constlsn_t lsnbuf_pool_get_oldest_modification_approx();constlsn_t laglog.recent_closed.capacity();lsn_t lwm_lsnlsn-lag;/* Note lsn up to which all dirty pages have already been added into Buffer Pool */constlsn_t dpa_lsnlog_buffer_dirty_pages_added_up_to_lsn(log);/* Final checkpoint position */lsn_t checkpoint_lsnstd::min(lwm_lsn,dpa_lsn);关键概念lwm_lsnBuffer Pool 中最老脏页的 LSNdpa_lsn已加入 Buffer Pool 的脏页最大 LSNrecent_closedlink_buf处理脏页注册的乱序问题 Checkpoint 存储位置ib_logfile0的 Block 1 和 Block 2交替写入防崩溃内容字段大小说明Checkpoint Number8B用于判断最新记录Checkpoint LSN8BCheckpoint 位置Checkpoint Offset8B文件偏移Log Buffer Size8B暂未使用恢复时从最新 Checkpoint LSN 开始重放后续 REDO。7️⃣ 总结特性说明核心作用保证事务持久性支持崩溃恢复设计思想Physiological Logging物理逻辑混合关键机制LSN 幂等、WAL、Double Write Buffer性能优化无锁并发写入、link_buf、专用唤醒线程空间管理Checkpoint 循环文件REDO LOG 是 InnoDB 实现事务持久性和崩溃恢复的基石。通过Physiological Logging、LSN 幂等机制、三层存储结构以及MySQL 8.0 的无锁并发写入架构InnoDB 在保证数据安全的同时极大提升了写入性能。理解 REDO LOG 的价值✅ 帮助 DBA 优化配置如innodb_log_file_size、innodb_flush_log_at_trx_commit✅ 为开发者设计高性能事务应用提供理论基础✅ 深入理解数据库内核工作原理8️⃣ 延伸阅读官方文档与源码MySQL 8.0 Redo Log FormatMySQL Source Code技术文章New Lock-free, Scalable WAL Design in MySQL 8.0How InnoDB handles REDO logging 本文基于 MySQL 8.0 源码分析
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2480052.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!