文章目录

  • 一、一些小概念
  • 1.1 MySQL的关闭相关参数
  • 1.2 MySQL启动相关参数
  • 1.3 innodb的两阶段提交
  • 二、MySQL的崩溃恢复
  • 2.1 前滚
  • 1、LSN点获取
  • 2、redo log前滚
  • 2.2 回滚
  • 1、undo恢复
  • 2、binlog恢复


一、一些小概念

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的两阶段提交

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

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是否完整判断是否回滚)。

文档参考:

http://mysql.taobao.org/monthly/2015/04/01/
http://www.sysdb.cn/index.php/2016/01/14/innodb-recovery/#more-17