Redo/Undo/Binlog + 两阶段提交 + BufferPool
一、Redo Log(重做日志)
1. 核心作用
保证事务持久性,用于数据库崩溃恢复。MySQL 修改数据不会直接写入磁盘,优先写入 redo log,机器重启后可根据日志重做数据,避免数据丢失。
2. 核心机制:WAL(预写日志)
先写日志,后写数据。所有数据修改操作,优先落盘 redo log,再异步刷新磁盘数据页。
目的:磁盘随机写速度极慢,redo log 是顺序写,极大提升数据库写入性能。
3. 顺序写特点
redo log 文件是固定大小、循环覆盖写入,属于磁盘顺序IO;对比数据表随机更新的随机IO,性能差距巨大,是InnoDB高性能的核心。
4. 崩溃恢复原理
数据库宕机后,内存数据丢失。重启时 MySQL 扫描 redo log:
-
已commit事务:重做,落地数据,保证持久
-
未commit事务:回滚,保证原子性
二、Undo Log(回滚日志)
1. 两大核心作用
-
事务回滚:保障事务原子性,事务异常时,通过undo log恢复数据修改前状态
-
实现MVCC:保存数据历史版本,通过回滚指针串联版本链,支撑RC、RR隔离级别快照读
2. 核心特性
undo log 记录的是数据修改前的快照,仅用于回滚和多版本读取,不参与数据持久化。
三、Binlog(二进制日志)
1. 归属引擎
MySQL Server层日志,所有存储引擎通用(区别于redo/undo属于InnoDB引擎层)。
2. 两大核心作用
-
数据恢复:基于binlog日志时间点,可恢复误删、误改的数据
-
主从同步:主库写入binlog,从库拉取日志重放,实现主从复制、读写分离
3. 日志格式(重点)
-
statement:记录SQL语句,体积小,部分函数场景主从数据不一致
-
row:记录行数据变更,精准无误差,体积大(生产主流)
-
mixed:混合模式,自动择优使用前两种格式
四、Redo Log 与 Binlog 核心区别(重点)
| 对比维度 | Redo Log | Binlog |
|---|---|---|
| 所属层级 | InnoDB 引擎层 | MySQL Server 层 |
| 核心作用 | 崩溃恢复、保证持久性 | 主从同步、数据备份恢复 |
| 记录内容 | 物理日志,记录数据页修改 | 逻辑日志,记录SQL/行数据变更 |
| 写入方式 | 循环覆盖写入 | 追加写入,日志永久递增 |
五、两阶段提交(2PC)(重中之重)
1. 存在意义
解决 redo log 和 binlog 数据一致性问题,保证两个日志要么同时成功,要么同时失败,避免主从数据不一致、数据丢失。
2. 完整执行流程
-
第一阶段(Prepare):事务执行DML操作,写入 redo log(标记prepare状态),此时 不写入binlog,不提交事务
-
第二阶段(Commit):redo log prepare成功后,写入 binlog 并落盘;binlog写入成功后,修改redo log状态为commit,事务正式提交
3. 宕机容错机制
-
Prepare 阶段宕机:无binlog记录,事务直接回滚
-
Prepare完成、Commit前宕机:重启后判断有redo prepare日志+无binlog,回滚事务;保证双日志一致
六、Buffer Pool、脏页与刷盘策略
1. Buffer Pool 作用
InnoDB 内存缓冲池,缓存磁盘数据页、索引页。所有数据读写优先走内存,大幅减少磁盘IO,是数据库高性能的核心。
2. 脏页定义
内存 Buffer Pool 中的数据页被修改,和磁盘原数据页不一致,该数据页即为脏页。
3. 脏页刷盘机制
数据修改只改内存,redo log记录变更,脏页会异步刷入磁盘,不会实时刷盘。
4. 四大刷盘触发时机
-
内存不足:Buffer Pool 空间不够,淘汰旧页,触发刷盘
-
redo log 写满:循环覆盖前,强制刷盘脏页
-
定时刷盘:后台线程定时刷新,保证数据落地
-
数据库关闭:全局刷盘,持久化所有脏数据