14.19.2 InnoDB 恢复

本节介绍InnoDB恢复。主题包括:

Point-in-Time Recovery

为了从进行物理备份时恢复InnoDB数据库到现在,您必须在启用二进制日志记录的情况下甚至在进行备份之前运行 MySQL 服务器。为了在还原备份后实现时间点恢复,您可以应用备份完成后二进制日志中的更改。参见第 7.5 节“时间点(增量)恢复”

从数据损坏或磁盘故障中恢复

如果数据库损坏或发生磁盘故障,则必须使用备份执行恢复。如果发生损坏,请首先找到未损坏的备份。还原基本备份后,使用mysqlbinlogmysql从二进制日志文件中进行时间点恢复,以还原进行备份后发生的更改。

在某些数据库损坏的情况下,足以转储,删除和重新创建一个或几个损坏的 table。您可以使用CHECK TABLE语句检查 table 是否损坏,尽管CHECK TABLE自然无法检测到每种可能的损坏。

在某些情况下,明显的数据库页面损坏实际上是由于 os 损坏了其自己的文件高速缓存,并且磁盘上的数据可能还可以。最好先尝试重新启动计算机。这样做可以消除似乎是数据库页面损坏的错误。如果 MySQL 由于InnoDB一致性问题而无法启动,请参阅第 14.22.2 节“强制 InnoDB 恢复”以恢复模式启动实例的步骤,该模式允许您转储数据。

InnoDB 故障恢复

要从 MySQL 服务器崩溃中恢复,唯一的要求是重新启动 MySQL 服务器。 InnoDB自动检查日志并执行数据库到当前的前滚。 InnoDB自动回滚崩溃时存在的未提交的事务。恢复期间,mysqld显示类似于以下内容的输出:

InnoDB: Log scan progressed past the checkpoint lsn 369163704
InnoDB: Doing recovery: scanned up to log sequence number 374340608
InnoDB: Doing recovery: scanned up to log sequence number 379583488
InnoDB: Doing recovery: scanned up to log sequence number 384826368
InnoDB: Doing recovery: scanned up to log sequence number 390069248
InnoDB: Doing recovery: scanned up to log sequence number 395312128
InnoDB: Doing recovery: scanned up to log sequence number 400555008
InnoDB: Doing recovery: scanned up to log sequence number 405797888
InnoDB: Doing recovery: scanned up to log sequence number 411040768
InnoDB: Doing recovery: scanned up to log sequence number 414724794
InnoDB: Database was not shutdown normally!
InnoDB: Starting crash recovery.
InnoDB: 1 transaction(s) which must be rolled back or cleaned up in
total 518425 row operations to undo
InnoDB: Trx id counter is 1792
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Progress in percent: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
InnoDB: Apply batch completed
...
InnoDB: Starting in background the rollback of uncommitted transactions
InnoDB: Rolling back trx with id 1511, 518425 rows to undo
...
InnoDB: Waiting for purge to start
InnoDB: 5.7.18 started; log sequence number 414724794
...
./mysqld: ready for connections.

InnoDB crash recovery包含几个步骤:

  • Tablespace discovery

table 空间发现是InnoDB用来标识需要重做日志应用程序的 table 空间的过程。参见故障恢复期间的 table 空间发现

重做日志应用程序在初始化期间执行,然后接受任何连接。如果在关闭或崩溃时将所有更改从buffer pool刷新到tablespaces(ibdata**.ibd文件),则会跳过重做日志应用程序。如果启动时缺少重做日志文件,InnoDB还将跳过重做日志应用程序。

不建议删除重做日志以加快恢复速度,即使有些数据丢失是可以接受的。仅在将innodb_fast_shutdown设置为01的干净关闭后,才考虑删除重做日志。

有关InnoDB用来标识需要重做日志应用程序的 table 空间的过程的信息,请参阅故障恢复期间的 table 空间发现

不完整的 Transaction 是发生崩溃或fast shutdown时处于活动状态的任何 Transaction。回滚不完整的事务所花费的时间可能是事务在被中断之前处于活动状态的时间的三到四倍,具体取决于服务器负载。

您无法取消正在回滚的事务。在极端情况下,当预计回滚事务将花费非常长的时间时,以_4 或更大的innodb_force_recovery设置启动InnoDB可能会更快。参见第 14.22.2 节“强制 InnoDB 恢复”

将更改从更改缓冲区(属于system tablespace的一部分)应用于辅助索引的叶页,因为将索引页读到了缓冲池。

删除已删除标记的记录,这些记录不再对活动事务可见。

重做日志应用程序之后的步骤不依赖于重做日志(除了记录写操作以外),并且与常规处理并行执行。其中,仅回滚不完整的事务对于崩溃恢复而言是特殊的。插入缓冲区合并和清除在正常处理期间执行。

重做日志应用程序后,InnoDB尝试尽早接受连接,以减少停机时间。作为崩溃恢复的一部分,当服务器崩溃时,InnoDB会回滚未提交或处于XA PREPARE状态的事务。回滚由后台线程执行,与来自新连接的事务并行执行。在回滚操作完成之前,新连接可能会与已恢复的事务发生锁定冲突。

在大多数情况下,即使在繁忙的活动中 MySQL 服务器被意外杀死,恢复过程也会自动发生,并且 DBA 无需采取任何措施。如果硬件故障或严重的系统错误损坏了InnoDB数据,MySQL 可能会拒绝启动。在这种情况下,请参见第 14.22.2 节“强制 InnoDB 恢复”

有关二进制日志和InnoDB故障恢复的信息,请参阅第 5.4.4 节“二进制日志”

故障恢复期间的 table 空间发现

如果在恢复过程中InnoDB遇到自上一个检查点以来写入的重做日志,则必须将重做日志应用于受影响的 table 空间。在恢复期间标识受影响的 table 空间的过程称为table 空间发现

table 空间发现是通过扫描从最后一个检查点到日志末尾的重做日志以查找在修改 table 空间页面时写入的MLOG_FILE_NAME条记录来执行的。 MLOG_FILE_NAME记录包含 table 空间空间 ID 和文件名。

启动时,InnoDB打开系统 table 空间并重做日志。如果自上一个检查点以来已写入重做日志记录,则将根据MLOG_FILE_NAME条记录打开受影响的 table 空间文件。

为所有持久性 table 空间类型写入MLOG_FILE_NAME条记录,包括每个 table 文件 table 空间,常规 table 空间,系统 table 空间和撤消日志 table 空间。

基于重做日志的发现具有以下 Feature:

  • 仅访问自上一个检查点以来已修改的 table 空间*.ibd文件。

  • 应用重做日志时,未附加到InnoDB实例的 table 空间*.ibd文件将被忽略。

  • 如果系统 table 空间的MLOG_FILE_NAME条记录与影响系统 table 空间数据文件名的服务器配置不匹配,则恢复将失败,并出现错误,然后应用重做日志。

  • 如果缺少在日志的扫描部分中引用的 table 空间文件,则将拒绝启动。

  • 仅当日志中有文件删除的重做日志记录(MLOG_FILE_DELETE)时,才会忽略缺少 table 空间*.ibd文件的重做日志。例如,table 重命名失败可能会导致“丢失”的*.ibd文件而没有MLOG_FILE_DELETE记录。在这种情况下,您可以手动重命名 table 空间文件并重新启动崩溃恢复,也可以使用innodb_force_recovery选项以恢复模式重新启动服务器。在恢复模式下启动服务器时,丢失的*.ibd文件将被忽略。

MySQL 5.7 中引入的基于重做日志的发现取代了早期 MySQL 版本中用于构建应用重做日志所需的“空间 ID 到 table 空间文件名”Map 的目录扫描。