MySQL崩溃恢复

本文深入解析MySQL的崩溃恢复机制,包括前滚与回滚的过程,以及两阶段提交在事务管理中的作用。探讨了innodb_force_recovery参数对恢复的影响,以及LSN点在redo日志恢复中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、一些小概念

1.1 MySQL的关闭相关参数

MySQL正常关闭时需要做哪些操作一般通过参数innodb_fast_shutdown进行控制,若MySQL异常关闭crash,那么就相当于innodb_fast_shutdown=2的情况,下面是该参数的详细介绍:

  • innodb_fast_shutdown

    0:在该模式下关闭MySQL时所做的操作是最多的,也是最耗时的,但是该模式下MySQL的启动是最快的,主要做三个动作:
    1)flush dirty pages(脏页落盘)
    2)merge change buffer(主要针对非唯一的二级索引)
    3)full purge(删除无用的undo)
    做 innodb plugin升级时,会设置为0,再正常关闭数据库。
    1:默认值,该模式下MySQL关闭时只需要做flush dirty pages
    2:该模式相当于MySQL的异常关闭crash,MySQL关闭时只需要将log buffer中的日志刷到logfile中,该模式下MySQL关闭耗时最短,但是MySQL启动时耗时最长,需要根据日志文件进行崩溃恢复。

1.2 MySQL启动相关参数

  • innodb_force_recovery

MySQL恢复时做哪些操作主要根据参数innodb_force_recovery进行控制,该参数越小检查项目越详细,越保证数据安全,以下是该参数详情解释

0:默认值、所有都检查
1:忽略检查corrupt页
2:阻止master线程运行,如果master线程需要执行full purge操作会导致crash
3:不执行事务回滚操作
4:不执行change buffer的合并操作
5:不检查undo log,innodb引擎会将未提交事务视为已提交
6:不执行前滚操作

当innodb_force_recovery 值为1-3时,仅允许SELECT TABLE ,DROP or CREATE tables;innodb_force_recovery 值为>=4时,5.7.17之前版本支持DROP TABLE,5.7.18后版本不支持。

1.3 innodb的两阶段提交

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VrkDigYA-1593157663191)(http://note.youdao.com/yws/res/57689/D6BE9FF0C25E41F5B32F40B2659FBC7D)]

对于一个更新操作,其两阶段提交主要流程为:

1)执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。

2)执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。

3)引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。

4)执行器生成这个操作的 binlog,并把 binlog 写入磁盘。(在提交的时候一次性写入)

5)执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。

二、MySQL的崩溃恢复

2.1 前滚

1、LSN点获取

MySQL正常关闭的情况下,flush dirty pages操作不仅会将缓冲池中所有脏页进行刷盘,而且会记录最新一条checkpoin lsn 到iddata文件的第一个page中。若MySQL的正常关闭和正常启动,在启动时会读取ibdata文件的第一个page中的lsn点,然后从该lsn点开始后续的redo恢复操作。若在获取ibdata第一个数据页中的lsn点时发现数据页损坏,MySQL会依次读取后面的数据页,直到有一个完整的数据页记录lsn点,然后根据该lsn点进行后续的redo恢复操作。

2、redo log前滚

MySQL根据上面找到的LSN点去扫描redo log,寻找mlog_checkpoint的位置信息,checkpoint lsn到mlog_checkpoint之间的信息表示需要恢复的所有数据。该过程具体主要分为三种场景:

1)若在redo log中没有找到mlog_checkpoint位置信息,说明该checkpoint lsn之后没有发生过数据更新,或者说MySQL属于正常关闭

2)若在redo log中发现多个mlog_checkpoint位置信息,说明redo log已经损坏,innodb报错退出

3)若在redo log中扫描到一个mlog_checkpoint位置信息,说明这部分数据是last checkpoint后的变更操作数据没有刷盘,需要应用这部分日志进行恢复。

2.2 回滚

1、undo恢复

数据库的所有变更操作(除临时表外)的undo日志也会记录到redo日志中,所以redo日志应用完毕后,innodb会对undo进行初始化,根据每个回滚段page中的slot是否被使用来恢复对应的undo log。该步骤将数据库恢复到了崩溃前的完整的事务状态。

开启一个后台线程来做事务回滚和清理操作。对于处于active状态的事务直接回滚(prepare状态之前的事务),对于既不active也非prepare状态的事务(已提交完成事务),直接则认为其是提交的,直接释放事务对象。该步骤主要是undo的恢复,undo恢复完成后,理论上事务链表上只存在处于prepare状态的事务,这些事务就需要通过binlog进入XA恢复。

2、binlog恢复

在初始化完成引擎后,Server层会开始扫描最后一个Binlog文件,搜集其中记录的xid(MYSQL_BIN_LOG::recover),然后和InnoDB层的事务xid做对比。如果xid已经存在于binlog中了,对应的事务需要提交,否则需要回滚事务(prepare节点之后,根据该事务binlog是否完整判断是否回滚)。

文档参考:

https://www.cnblogs.com/xinysu/p/6586386.html#_lab2_1_0
http://mysql.taobao.org/monthly/2015/04/01/
http://www.sysdb.cn/index.php/2016/01/14/innodb-recovery/#more-17
https://www.cnblogs.com/coderyuhui/p/7191413.html

<think>嗯,用户现在想了解MySQL崩溃恢复redo log和undo log的执行顺序。之前已经详细讨论过redo log和binlog的区别,用户可能是在深入学习事务机制时遇到了这个问题。 从引用内容看,用户提供的参考资料很专业,特别是引用[1]和[2]详细解释了两种日志的机制。用户似乎已经理解了基本概念,现在更关注它们在崩溃恢复时的交互顺序。 注意到引用[2]特别强调“Redo Log记录物理修改”和“BinLog记录逻辑修改”的区别,这很重要。在崩溃恢复场景下,物理日志必须先处理,因为需要先修复数据页的物理状态,才能进行后续逻辑操作。 用户引用的资料中还提到undo log的删除机制(引用[4])和LSN记录(引用[3]),这些都会影响恢复流程。需要把这些点融入解释中。 考虑到用户之前的问题都比较深入,这次回答应该: 第一,明确分步骤说明恢复流程 第二,用LSN作为关键线索串联整个过程 第三,强调undo log在回滚阶段的决定性作用 第四,补充一个典型崩溃场景的示例 需要特别注意技术细节的准确性: - redo log的prepare状态如何影响恢复判断 - 为什么undo log的应用必须在redo log之后 - 检查点(checkpoint)在恢复时的关键作用 最后生成的思考题要延续事务日志的主题,比如两阶段提交的崩溃处理、undo log存储优化等,帮助用户建立系统认知。</think>在MySQL崩溃恢复过程中,**redo log和undo log的执行顺序严格遵循“先重做(redo)后回滚(undo)”的原则**,具体流程如下: --- ### **崩溃恢复核心流程** #### **1. 重做阶段 (Redo Phase)** ```mermaid graph LR A[崩溃重启] --> B[扫描redo log] B --> C{检查LSN<br>(Log Sequence Number)} C -->|定位| D[最近检查点] D --> E[重做所有已提交/未提交事务的修改] E --> F[将数据页恢复崩溃前状态] ``` - **执行顺序**: 1️⃣ 从最近检查点(Checkpoint)开始扫描redo log 2️⃣ 按LSN顺序**重放所有物理修改**(包括已提交和未提交事务)[^3] 3️⃣ 将数据页恢复崩溃瞬间的物理状态 - **关键点**: - 此阶段**仅依赖redo log**,无视事务状态 - 通过`Write-Ahead Logging`机制确保数据页完整性[^1][^2] #### **2. 回滚阶段 (Undo Phase)** ```mermaid graph LR G[扫描undo log] --> H{事务状态判断} H -->|未提交事务| I[应用undo log回滚] H -->|已提交事务| J[跳过] I --> K[生成回滚SQL<br>撤销修改] ``` - **执行顺序**: 1️⃣ 扫描undo log链,识别所有**未提交事务**(通过事务状态标记) 2️⃣ 按事务逆向应用undo log,执行回滚操作 3️⃣ 释放未提交事务占用的锁和资源[^4] - **关键点**: - 仅处理**未提交事务**,已提交事务跳过 - undo log通过**指针链式结构**保证回滚顺序[^1][^4] --- ### **执行顺序的深层逻辑** 1. **物理优先于逻辑** - redo log记录**物理页修改**(如“页#5偏移0x10写入值0xFF”),需优先恢复数据页基础结构[^2] - undo log记录**逻辑操作**(如“原始值0x00”),依赖完整的数据页才能执行回滚 2. **事务状态依赖** - 崩溃瞬间事务状态丢失,需先通过redo log恢复数据页,才能从页中读取事务ID和状态标记 - 例如:数据页的事务ID是判断是否回滚的关键依据 3. **LSN的协同作用** | 日志类型 | 作用 | 恢复阶段 | |---|---|---| | redo log LSN | 定位检查点,确定重做起点 | 重做阶段[^3] | | undo log LSN | 关联事务修改顺序,确保回滚一致性 | 回滚阶段 | --- ### **典型崩溃场景示例** 假设事务A(已提交)和事务B(未提交)同时修改行R: 1. **崩溃发生前** - redo log:记录A和B对数据页的物理修改 - undo log:记录B修改前的原始值 2. **恢复过程** - **重做阶段**: redo log同时恢复A和B的修改 → 行R包含A和B的修改结果 - **回滚阶段**: undo log检测到B未提交 → 用undo log撤销B的修改 → 行R仅保留A的修改 > 💎 **结论**: > redo log确保**数据不丢失**,undo log确保**事务原子性**。二者通过LSN和事务状态协同工作,最终达成数据一致性[^1][^2][^4]。 --- ### **相关问题** 1. 为什么MySQL需要先执行redo log再执行undo log? 2. 在崩溃恢复过程中,如何通过LSN定位检查点(checkpoint)? 3. undo log的回滚操作是否会再次产生redo log记录? 4. 如果崩溃发生在undo log写入过程中,恢复流程如何处理?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值