程序员社区

梳理下MySQL崩溃恢复过程

基于MySQL5.7版本,5.7版本在恢复过程做了优化,本文描述不考虑之前版本。梳理下MySQL崩溃恢复过程插图

1 初始化崩溃恢复

    数据库关闭只有2种情况,正常关闭,非正常关闭(包括数据库实例crash及服务器crash)。

    正常关闭情况,所有buffer pool里边的脏页都会都会刷新一遍到磁盘,同时记录最新LSN到ibdata文件的第一个page中。而非正常关闭来不及做这些操作,也就是没及时把脏数据flush到磁盘,也没有记录最新LSN到ibdata file。

    当我们重启数据库实例的时候,数据库做2个阶段性操作:redo log处理,undo log及binlog 处理。

1.1 redo log处理

  • 打开系统表空间ibdata,读取第一个page中的LSN,若第一个页损坏,则依次往后面的page读,知道有个完整的page能够提供LSN,这个LSN当作上次shutdown时的checkpoint点,后续恢复,从这个LSN点开始恢复
  • 进入redo log文件,读取第一个redo log文件头的checkpoint LSN, 并根据该LSN定位到redo日志文件中对应的位置,从该checkpoint点开始扫描,进行3次redo log文件扫描:
    • 第一次,找 MLOG_CHECKPOINT日志
      • 如果是正常关闭,这个日志是不做记录的,也就是扫描的过程中不回找到对应的MLOG_CHECKPOINT日志,不会进行接下来的两次扫描,因为属于正常关闭数据库服务,不需要考虑奔溃恢复情况;
      • 如果是非正常关闭,则会查找到 MLOG_CHECKPOINT (如果是多个,则说明redo文件已损坏,恢复报错),获取MLOG_FILE_NAME中指定后续需要恢复的ibd文件;
    • 第二次,从redo log读到的LSN,找到checkpoint点开始重复扫描存储日志对象
      • 根据MLOG_CHECKPOINT日志,读取对应LSN之后的日志解析到hash表中,如果剩下的日志解析结束后还没有填满hash表格,则不需要进行第三次扫描;
      • 进行到这里,则说明数据库是非正常关闭,会在errorlog中提示:Database was not shutdown normally!详见下图。
      • 梳理下MySQL崩溃恢复过程插图1
    • 第三次,若第二次扫描hash表空间不足,则发起第三次扫描,清空hash表空间,重新从新的checkpoint点开始扫描
      • 如果第二次扫扫描就把hash表填满,那么会先把hash表里边的记录重做到buffer pool中的数据页,然后再来加载redo log 记录到被清空的hash表中,hash表满后立即执行恢复操作,知道所有需要redo 的redo log 被应用结束。

    恢复的过程中,注意两个点:打开ibd文件形式,读取数据库到buffer pool的改进。

    根据hash表中的相应信息读取数据页, 读数据页的时候,5.7之前版本采用把所有表空间都打开,所有表格仅执行ReadOnly,5.7版本做了优化,新增了 MLOG_FILE_NAME 记录在checkpoint之后,所有被修改过的信息,根据这些信息,在恢复过程中,只需要打开相应的ibd文件即可,不涉及恢复的表格支持正常DML跟DDL操作,涉及恢复的表格则仅执行ReadOnly功能。

    当把数据页读取到buffer pool中,以往版本是只读取对应的单个页面,而现在的是直接读取与该页面相邻的32个data page 也一起加载的buffer pool,因为一个数据页的修改,可能周围的页面也被修改,一次性读取,可以避免后面根据hash表中再重新读取其相邻的页面。

1.2 undo log及binlog 处理

      上一阶段中,把redo log中的操作都apply到数据页中,但是对于prepare状态的事务却还没有进行回滚处理,这个阶段则是针对prepare状态的事务进行处理,需要使用到binlog和undo log。

  • 根据最后一个binlog文件,为啥不是所有binlog文件呢?因为每一个binlog文件切换的时候,都会确保当前binlog文件的所有操作已落盘,所以只需要考虑最后一个binlog文件。跟进最后一个binlog文件,获取所有可能没有提交事务的xid列表;
  • 根据undo log中的 insert_undo_list,upddate_undo_list事务链,构建undo_list,在根据undo_list构建未提交事务链表;
  • 从未提交事务链表中,提取出xid,凡是存在于xid列表中的,则需要提交,不存在的,则回滚。

      整个恢复过程,可以参考下来自 www.sysdb.cn 网站作者  boyce 画的说明图,图片版权属于该作者,本处仅为引用分享给大家,作图很详细,一言不合开源码分析!遗憾的是,作者只写了2篇博文就停止更新了,心疼默哀十分钟.....