### 15.18.2 InnoDB 恢复

[](<>)[](<>)

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

-   [时间点恢复](innodb-recovery.html#innodb-recovery-point-in-time)

-   [从数据损坏或磁盘故障中恢复](innodb-recovery.html#innodb-corruption-disk-failure-recovery)

-   [InnoDB 崩溃恢复](innodb-recovery.html#innodb-crash-recovery)

-   [崩溃恢复期间的表空间发现](innodb-recovery.html#innodb-recovery-tablespace-discovery)

#### 时间点恢复

[](<>)[](<>)

恢复一个`InnoDB`从进行物理备份的时间到现在，您必须在启用二进制日志记录的情况下运行 MySQL 服务器，甚至在进行备份之前。要在还原备份后实现时间点恢复，您可以应用备份后发生的二进制日志中的更改。看[第 7.5 节，“时间点（增量）恢复”](point-in-time-recovery.html).

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

[](<>)[](<>)[](<>)[](<>)

如果您的数据库损坏或发生磁盘故障，您必须使用备份执行恢复。在损坏的情况下，首先找到未损坏的备份。还原基本备份后，使用二进制日志文件执行时间点恢复[**mysqlbinlog**](mysqlbinlog.html)和[**mysql**](mysql.html)恢复备份后发生的更改。

在某些数据库损坏的情况下，转储、删除和重新创建一个或几个损坏的表就足够了。您可以使用[`检查表`](check-table.html)检查表是否损坏的语句，尽管[`检查表`](check-table.html)自然无法检测到每一种可能的腐败。

在某些情况下，明显的数据库页面损坏实际上是由于操作系统损坏了自己的文件缓存，而磁盘上的数据可能没有问题。最好先尝试重新启动计算机。这样做可以消除看起来是数据库页面损坏的错误。如果 MySQL 仍然无法启动，因为`InnoDB`一致性问题，见[第 15.21.3 节，“强制 InnoDB 恢复”](forcing-innodb-recovery.html)有关在恢复模式下启动实例的步骤，该模式允许您转储数据。

#### InnoDB 崩溃恢复

[](<>)[](<>)

要从 MySQL 服务器意外退出中恢复，唯一的要求是重新启动 MySQL 服务器。`InnoDB`自动检查日志并将数据库前滚到现在。`InnoDB`自动回滚崩溃时存在的未提交事务。康复期间，[**mysqld**](mysqld.html)显示与此类似的输出：

```
InnoDB: The log sequence number 664050266 in the system tablespace does not match
the log sequence number 685111586 in the ib_logfiles!
InnoDB: Database was not shutdown normally!
InnoDB: Starting crash recovery.
InnoDB: Using 'tablespaces.open.2' max LSN: 664075228
InnoDB: Doing recovery: scanned up to log sequence number 690354176
InnoDB: Doing recovery: scanned up to log sequence number 695597056
InnoDB: Doing recovery: scanned up to log sequence number 700839936
InnoDB: Doing recovery: scanned up to log sequence number 706082816
InnoDB: Doing recovery: scanned up to log sequence number 711325696
InnoDB: Doing recovery: scanned up to log sequence number 713458156
InnoDB: Applying a batch of 1467 redo log records ...
InnoDB: 10%
InnoDB: 20%
InnoDB: 30%
InnoDB: 40%
InnoDB: 50%
InnoDB: 60%
InnoDB: 70%
InnoDB: 80%
InnoDB: 90%
InnoDB: 100%
InnoDB: Apply batch completed!
InnoDB: 1 transaction(s) which must be rolled back or cleaned up in total 561887 row
operations to undo
InnoDB: Trx id counter is 4096
...
InnoDB: 8.0.1 started; log sequence number 713458156
InnoDB: Waiting for purge to start
InnoDB: Starting in background the rollback of uncommitted transactions
InnoDB: Rolling back trx with id 3596, 561887 rows to undo
...
./mysqld: ready for connections....
```

[](<>)

`InnoDB` [崩溃恢复](glossary.html#glos_crash_recovery)包括几个步骤：

-   表空间发现

    表空间发现是一个过程`InnoDB`用于标识需要重做日志应用程序的表空间。看[崩溃恢复期间的表空间发现](innodb-recovery.html#innodb-recovery-tablespace-discovery).

-   [重做日志](glossary.html#glos_redo_log)应用

    重做日志应用程序在初始化期间执行，在接受任何连接之前。如果所有更改都从[缓冲池](glossary.html#glos_buffer_pool)到[表空间](glossary.html#glos_tablespace)(`数据*`和`*.ibd`文件）在关机或崩溃时，跳过重做日志应用程序。`InnoDB`如果重做日志文件在启动时丢失，也会跳过重做日志应用程序。

    -   每次值更改时，当前最大的自动增量计数器值都会写入重做日志，这使其具有崩溃安全性。康复期间，`InnoDB`扫描重做日志以收集计数器值更改并将更改应用于内存表对象。

        有关如何的更多信息`InnoDB`处理自动递增值，请参阅[第 15.6.1.6 节，“自动\_InnoDB 中的增量处理”](innodb-auto-increment-handling.html)， 和[InnoDB 自动\_INCREMENT 计数器初始化](innodb-auto-increment-handling.html#innodb-auto-increment-initialization).

    -   当遇到索引树损坏时，`InnoDB`将损坏标志写入重做日志，这使得损坏标志是安全的。`InnoDB`还将内存中的损坏标志数据写入每个检查点上的引擎专用系统表。康复期间，`InnoDB`在将内存表和索引对象标记为损坏之前，从两个位置读取损坏标志并合并结果。

    -   不建议删除重做日志以加快恢复速度，即使某些数据丢失是可以接受的。只有在干净关闭后才应考虑删除重做日志，使用[`innodb_fast_shutdown`](innodb-parameters.html#sysvar_innodb_fast_shutdown)调成`0`要么`1`.

-   [回滚](glossary.html#glos_rollback)不完整的[交易](glossary.html#glos_transaction)

    不完整交易是指在意外退出时处于活动状态的任何交易或[快速关机](glossary.html#glos_fast_shutdown).回滚不完整事务所需的时间可能是事务在中断之前处于活动状态的时间的三到四倍，具体取决于服务器负载。

    您不能取消正在回滚的事务。在极端情况下，当回滚事务预计需要非常长的时间时，启动可能会更快`InnoDB`与[`innodb_force_recovery`](innodb-parameters.html#sysvar_innodb_force_recovery)的设置`3`或更大。看[第 15.21.3 节，“强制 InnoDB 恢复”](forcing-innodb-recovery.html).

-   [更改缓冲区](glossary.html#glos_change_buffer)合并

    从更改缓冲区应用更改（部分[系统表空间](glossary.html#glos_system_tablespace)) 到二级索引的叶子页面，因为索引页面被读取到缓冲池。

-   [清除](glossary.html#glos_purge)

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

    重做日志应用程序之后的步骤不依赖于重做日志（除了记录写入），并且与正常处理并行执行。其中，只有不完整事务的回滚对崩溃恢复是特殊的。插入缓冲区合并和清除在正常处理期间执行。

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

    在大多数情况下，即使 MySQL 服务器在繁重的活动中意外终止，恢复过程也会自动发生，不需要 DBA 采取任何措施。如果硬件故障或严重的系统错误损坏`InnoDB`数据，MySQL 可能会拒绝启动。在这种情况下，请参阅[第 15.21.3 节，“强制 InnoDB 恢复”](forcing-innodb-recovery.html).

    有关二进制日志的信息和`InnoDB`崩溃恢复，见[第 5.4.4 节，“二进制日志”](binary-log.html).

#### 崩溃恢复期间的表空间发现

[](<>)[](<>)

如果在恢复过程中，`InnoDB`遇到自上次检查点以来写入的重做日志，重做日志必须应用于受影响的表空间。在恢复期间识别受影响的表空间的过程称为*表空间发现*.

表空间发现依赖于[`innodb_directories`](innodb-parameters.html#sysvar_innodb_directories)设置，它定义了在启动时扫描表空间文件的目录。这[`innodb_directories`](innodb-parameters.html#sysvar_innodb_directories)默认设置为 NULL，但定义的目录由[`innodb_data_home_dir`](innodb-parameters.html#sysvar_innodb_data_home_dir),[`innodb_undo_directory`](innodb-parameters.html#sysvar_innodb_undo_directory)， 和[`数据目录`](server-system-variables.html#sysvar_datadir)总是附加到[`innodb_directories`](innodb-parameters.html#sysvar_innodb_directories)InnoDb 在启动时构建要扫描的目录列表时的参数值。无论是否添加了这些目录[`innodb_directories`](innodb-parameters.html#sysvar_innodb_directories)设置是明确指定的。使用绝对路径定义的或位于附加到目录之外的表空间文件[`innodb_directories`](innodb-parameters.html#sysvar_innodb_directories)设置应添加到[`innodb_directories`](innodb-parameters.html#sysvar_innodb_directories)环境。如果之前没有发现重做日志中引用的任何表空间文件，则恢复将终止。
