mysql crash recovery_InnoDB crash recovery 过程和疑问

参考资料

相关知识点

LSN

LSN(log sequence number) 用于记录日志序号,它是一个不断递增的 unsigned long long 类型整数;

在 redo log 中,以 512 字节 block 对齐写入文件(最小单位 block,大小为 512 字节),通过LSN,可以具体的定位到其在redo log文件中的位置;

在 buffer pool 中,flush list 上的 page 按照修改这些 page 的 LSN 号进行排序。

checkpoint

buffer pool 中的脏页刷盘时,从 flush list 尾部开始将数据页 fsync 到磁盘,并把最后一页的 LSN 记为 last checkpoint LSN,写入到 redo log 的头部;

也可以调用log_checkpoint() 完成 checkpoint 的写入,此时只会把 flush list 中最老的 LSN 写入到 redo log 头部,并不会刷脏页。

逻辑流程

当正常 shutdown 实例时,会将所有的脏页都刷到磁盘,并做一次完全同步的 checkpoint;同时将最后的 lsn 写到系统表 ibdata 的第一个 page 中(函数fil_write_flushed_lsn)。在重启时,可以根据该lsn来判断这是不是一次正常的 shutdown,如果不是就需要去做崩溃恢复逻辑;

表空间发现

即找到从 last checkpoint LSN 后做过修改的表空间文件,避免打开所有的表空间。是通过 MLOG_FILE_NAME 来实现的:在一次 checkpoint 后第一次修改某个表的数据时,总是先写一条 MLOG_FILE_NAME 日志,记录 space ID 和文件名。

应用 redo log

打开上一步得到的表空间,依次将 page 读入内存;从 redo log file 中获取 last checkpoint LSN,应用所有大于这个 LSN 的 redo log(只有LSN大于数据页上LSN的日志才会被应用)

遍历每个回滚段的 insert_undo_list 与update_undo_list,取出的undo,根据undo日志信息,重建事务;并且根据事务的不同状态:

a. undo 事务状态为TRX_UNDO_ACTIVE,为活跃事务,TRX_ACTIVE

b. undo 事务状态为TRX_UNDO_PREPARED -> TRX_PREPARED

回滚处于 ACTIVE 状态的 DDL、DML 事务。而处于 PREPARE 状态的事务需要与 binlog 结合判断:

a. 如果这个事务已经持久化到 binlog 中,即有 XID event,则不需要回滚这个事务

b. 如果没有持久化到 binlog 中,则回滚

案例

分析一个 crash recovery 失败的异常案例:MySQL意外关闭,之后误删除 redo log,启动报错:

2020-05-28T10:35:26.800467+08:00 0 [Note] InnoDB: Log scan progressed past the checkpoint lsn 2437132

2020-05-28T10:35:26.800498+08:00 0 [Note] InnoDB: Doing recovery: scanned up to log sequence number 2437160

2020-05-28T10:09:06.785759+08:00 0 [Note] InnoDB: Starting crash recovery.

2020-05-28T10:09:06.809837+08:00 0 [ERROR] InnoDB: Page [page id: space=0, page number=7] log sequence number 8403155287 is in the future! Current system log sequence number 2437150.

2020-05-28T10:09:06.809917+08:00 0 [ERROR] InnoDB: Your database may be corrupt or you may have copied the InnoDB tablespace but not the InnoDB log files. Please refer to http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html for information about forcing recovery.

2020-05-28T10:09:06.811243+08:00 0 [ERROR] InnoDB: Page [page id: space=0, page number=4] log sequence number 8405956349 is in the future! Current system log sequence number 2437150.

原因:

意外关闭意味着有脏页没有 fsync 到磁盘,所有下一次启动需要做 crash recovery

crash recovery 需要读取 redo log 中的 last checkpoint LSN,和 MLOG_FILE_NAME(记录table space ID 和文件名),然后对这些表空间的数据页从 checkpoint LSN 开始重做数据

但是由于删除了 redo log,启动时会重新创建 redo log,checkpoint LSN 会初始化成一个很小的值:2437132

而 MLOG_FILE_NAME 记录的 table space ID 的数据页上的 LSN 却比 last checkpoint LSN 还大,这是不应该的(正常来说,每个数据页有 LSN,在刷盘时,会从拥有最老 LSN 的数据页开始按顺序刷盘,然后把最后一个数据页的 LSN 记为 last checkpoit LSN,所以磁盘上的数据页的 LSN 肯定小于 last checkpoit LSN)。所以报这个错误。

疑问

关于 innodb_force_recovery=3 和 5 的区别在哪里?

580ab3302013

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值