【MySQL 三大日志深度解析】:redo log、undo log、binlog 作用与两阶段提交原理
你好我是fengxin_rou这是我的个人主页fengxin_rou的主页❄️欢迎查看我的专栏我的专栏《Java后端学习》、《JAVASE基础》、《JUC并发》、《redis》、《JVM虚拟机》、《MYSQL》、《黑马点评》、《rabbitmq》、《JavaWebAI的talis学习系统》、《苍穹外卖》前言MYSQL已经学习过了事务和锁今天就来讲一讲日志的相关知识主要讲解了mysql的三大日志以及其对应的作用并且探究了mysql是如何做到数据持久化遇到mysql重启时数据丢失怎么恢复mysql在提交事务时redolog和binlog的两阶段提交原理一、MySQL 三大日志核心作用MySQL 有三种最核心的日志1. redo log重做日志作用是InnoDB的引擎层生成的日志保证事务持久性用于掉电等故障恢复属于 InnoDB 引擎层日志记录物理日志某个数据页被修改了什么固定大小、循环写核心价值事务提交不用立即刷盘MySQL 重启后能把已提交事务 “重做” 回来2. undo log回滚日志作用是InnoDB的引擎层生成的日志保证事务原子性事务回滚支撑 MVCC记录逻辑日志数据修改前的样子用于事务回滚、多版本并发控制不参与崩溃恢复负责 “可回滚、可快照”3. binlog归档日志作用是一种二进制日志文件是Servicer层日志数据归档、主从复制、时间点恢复属于 MySQL Server 层日志记录逻辑变更SQL 或行变化追加写、可无限扩容支撑主从同步、增量备份、数据回档二、redo log 为什么能保证崩溃恢复WAL 机制1. 什么是 WALWAL Write-Ahead Logging预写日志核心思想先写日志再写磁盘。如果每次事务提交都直接刷数据页随机 I/O 极慢高并发下数据库直接卡死WAL 做法事务修改内存页Buffer Pool写入 redo log buffer事务提交时只需要把 redo log 刷入磁盘数据页慢慢后台刷盘即可只要 redo log 落盘成功数据就永久安全。2. redo log 崩溃恢复流程MySQL 运行中宕机内存数据丢失重启后 InnoDB 扫描 redo log把已提交但未刷盘的数据重新 “重做” 到数据页数据库恢复到崩溃前一致状态这就是 redo log 最核心的价值保证事务持久性 大幅提升写入性能。3.Redo log的顺序写入redo log采用追加写入的方式将redo日志记录追加到文件末尾而不是随机写入。这样可以减少磁盘的随机I/O操作提高写入性能因为redo log是一个环形大小的缓冲区那么在末尾时会从头开始写覆盖已经刷盘、不再需要的旧记录(循环写)4.Checkpoint机制因为数据库会定期将内存中的数据刷新到磁盘此时就会将最新的LSN(log sequence number)写入磁盘LSN标志了当前redo log刷新磁盘的操作到哪一个位置了。这个 LSN 表示此 LSN 之前的数据都已经安全落盘。所以总体流程就是数据页 MySQL 真实落在磁盘上的数据文件.ibd崩溃前磁盘数据页的 LSN 一定 ≤ redo log 的 LSN恢复时从「较小的那个 LSN数据页 LSN」开始重做 redo log 里更大、更新的部分最终把内存没来得及刷盘的数据重新补写到磁盘数据页里三、binlog 是什么statement /row/mixed 区别binlog 是 MySQLServer 层的逻辑日志Server层每进行一次数据操作就会生成一条binlog等事务结束后统一把所有binlog写入binlog文件并且binlog不会记录select语句只会记录修改表结构和数据的语句binlog是追加写一个文件写满后再新建一个文件继续写。1. binlog 三大格式对比1STATEMENT 模式又称逻辑日志每进行执行一条sql语句就记录SQL 语句原文主从复制中 slave 端再根据 SQL 语句重现优点日志小、性能好缺点有动态函数问题如uuid、now这样随时在变函数会导致主从节点不一致MySQL 5.7.7 之后将默认格式改为 ROW 的主要原因。2ROW 模式企业推荐MySQL 5.7.7 及之后的默认格式记录行的修改前后数据一条update语句修改了多少行数据就记录多少行优点主从完全一致、安全、可精准恢复不会有动态函数问题缺点日志体积稍大现在互联网公司默认使用 ROW3MIXED 模式混合 STATEMENT 和 ROW简单 SQL 用 STATEMENT不安全 SQL 自动切 ROW折中方案逐步被 ROW 取代结论生产环境直接用 ROW 格式。四、redo log 和 binlog 的核心区别对比项redo logbinlog所属层级InnoDB 引擎层MySQL Server 层日志类型物理日志数据页修改逻辑日志SQL / 行变化写入方式循环写固定大小追加写无限文件主要作用崩溃恢复主从复制、数据备份事务保证保证 ACID 持久性不保证事务只记录变更生成时机事务执行中持续写事务提交时一次性写一句话记忆redo 管崩溃bin 管复制。五、事务提交redo log binlog 两阶段提交原理1. 为什么需要两阶段提交如果没有两阶段提交redo 写成功、binlog 没写 → 主库恢复了数据从库没有binlog 写成功、redo 没写 → 从库有数据主库没有 最终导致主从数据不一致。两阶段提交就是为了让 redo log 与 binlog 逻辑完全一致。2. 两阶段提交完整流程阶段 1prepare 准备阶段InnoDB 将 redo log 写盘标记事务为prepare 状态未最终提交阶段 2写入 binlog执行器写 binlog刷盘成功才算事务真正成功阶段 3commit 提交阶段InnoDB 将 redo log 标记为commit 状态事务完成3. 崩溃恢复怎么判断prepare 阶段将 XID内部 XA 事务的 ID 写入到 redo log同时将 redo log 对应的事务状态设置为 prepare然后将 redo log 持久化到磁盘innodb_flush_log_at_trx_commit 1 的作用commit 阶段把 XID 写入到 binlog然后将 binlog 持久化到磁盘sync_binlog 1 的作用接着调用引擎的提交事务接口将 redo log 状态设置为 commit此时该状态并不需要持久化到磁盘只需要 write 到文件系统的 page cache 中就够了因为只要 binlog 写磁盘成功就算 redo log 的状态还是 prepare 也没有关系一样会被认为事务已经执行成功prepare阶段是XID写入redo log, commit阶段是XID写入binlog如果 binlog 中没有当前内部 XA 事务的 XID说明 redolog 完成刷盘但是 binlog 还没有刷盘则回滚事务。对应时刻 A 崩溃恢复的情况。如果 binlog 中有当前内部 XA 事务的 XID说明 redolog 和 binlog 都已经完成了刷盘则提交事务。对应时刻 B 崩溃恢复的情况。如果 binlog 已写入 redo 是 commit (时刻B后)→ 提交如果 binlog 已写入 redo 是 prepare (时刻B前)→ 提交如果 binlog 未写入(时刻A) → 回滚即只要 binlog 已经写入了该事务的 XID事务 ID恢复时就一定会把事务提交不管此时 redo log 是prepare还是commit状态。两阶段提交 MySQL 分布式事务的基石。六、UndoLog日志的作用是什么undo log是用于回滚的日志在一个事务中记录sql语句执行前的数据在失败之后就做sql语句的反操作来回退在插入一条记录时要把这条记录的主键值记下来这样之后回滚时只需要把这个主键值对应的记录删掉就好了在删除一条记录时要把这条记录中的内容都记下来这样之后回滚时再把由这些内容组成的记录插入到表中就好了在更新一条记录时要把被更新的列的旧值记下来这样之后回滚时再把这些列更新为旧值就好了。