### 15.6.5 重做日志

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

重做日志是一种基于磁盘的数据结构，用于在崩溃恢复期间纠正由不完整事务写入的数据。在正常操作期间，重做日志对由 SQL 语句或低级 API 调用产生的更改表数据的请求进行编码。在意外关闭之前未完成更新数据文件的修改会在初始化期间和接受连接之前自动重播。有关重做日志在崩溃恢复中的作用的信息，请参阅[第 15.18.2 节，“InnoDB 恢复”](innodb-recovery.html).

默认情况下，重做日志在磁盘上由两个名为`ib_logfile0`和`ib_logfile1`.MySQL 以循环方式写入重做日志文件。重做日志中的数据根据​​受影响的记录进行编码；这些数据统称为重做。数据通过重做日志的通道由一个不断增加的[LSN](glossary.html#glos_lsn)价值。

与重做日志相关的信息和过程在本节中的以下主题下进行了描述：

-   [更改重做日志文件的数量或大小](innodb-redo-log.html#innodb-redo-log-file-reconfigure)

-   [重做日志刷新的组提交](innodb-redo-log.html#innodb-performance-group_commit)

-   [重做日志归档](innodb-redo-log.html#innodb-redo-log-archiving)

-   [禁用重做日志](innodb-redo-log.html#innodb-disable-redo-logging)

-   [相关话题](innodb-redo-log.html#innodb-redo-log-related-topics)

#### 更改重做日志文件的数量或大小

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

更改数量或大小[重做日志](glossary.html#glos_redo_log)文件，请执行以下步骤：

1.  停止 MySQL 服务器并确保它在没有错误的情况下关闭。

2.  编辑`我的.cnf`更改日志文件配置。要更改日志文件大小，请配置[`innodb_log_file_size`](innodb-parameters.html#sysvar_innodb_log_file_size).要增加日志文件的数量，请配置[`innodb_log_files_in_group`](innodb-parameters.html#sysvar_innodb_log_files_in_group).

3.  再次启动 MySQL 服务器。

    如果`InnoDB`检测到[`innodb_log_file_size`](innodb-parameters.html#sysvar_innodb_log_file_size)不同于重做日志文件的大小，它写入一个日志检查点，关闭和删除旧的日志文件，以请求的大小创建新的日志文件，并打开新的日志文件。

#### 重做日志刷新的组提交

[](<>)

`InnoDB`, 像任何其他[酸](glossary.html#glos_acid)- 兼容的数据库引擎，刷新[重做日志](glossary.html#glos_redo_log)事务在提交之前。`InnoDB`用途[组提交](glossary.html#glos_group_commit)将多个刷新请求组合在一起的功能，以避免每次提交都刷新一次。通过组提交，`InnoDB`向日志文件发出单次写入，以对几乎同时提交的多个用户事务执行提交操作，从而显着提高吞吐量。

#### 重做日志归档

[](<>)

复制重做日志记录的备份实用程序有时可能无法在备份操作进行时跟上重做日志的生成速度，从而导致由于这些记录被覆盖而丢失重做日志记录。此问题最常发生在备份操作期间 MySQL 服务器有大量活动时，并且重做日志文件存储介质的运行速度比备份存储介质快。MySQL 8.0.17 中引入的重做日志归档功能通过将重做日志记录顺序写入归档文件和重做日志文件来解决此问题。备份实用程序可以根据需要从归档文件中复制重做日志记录，从而避免潜在的数据丢失。

如果在服务器上配置了重做日志归档，[MySQL 企业备份](https://dev.mysql.com/doc/mysql-enterprise-backup/8.0/en/), 可与[MySQL企业版](https://www.mysql.com/products/enterprise/)，在备份 MySQL 服务器时使用重做日志归档功能。

在服务器上启用重做日志归档需要为[`innodb_redo_log_archive_dirs`](innodb-parameters.html#sysvar_innodb_redo_log_archive_dirs)系统变量。该值被指定为以分号分隔的标记重做日志归档目录列表。这`*`标签：目录`*`对由冒号分隔 (`：`）。例如：

```
mysql> SET GLOBAL innodb_redo_log_archive_dirs='label1:directory_path1[;label2:directory_path2;…]';
```

这*`标签`*是存档目录的任意标识符。它可以是任何字符串，但不允许使用冒号 (:)。也允许使用空标签，但在这种情况下仍需要冒号 (:)。一种*`目录路径`*必须指定。激活重做日志归档时，为重做日志归档文件选择的目录必须存在，否则返回错误。路径可以包含冒号 (':')，但不允许使用分号 (;)。

这[`innodb_redo_log_archive_dirs`](innodb-parameters.html#sysvar_innodb_redo_log_archive_dirs)必须先配置变量，然后才能激活重做日志归档。默认值为`空值`，它不允许激活重做日志归档。

笔记

您指定的归档目录必须满足以下要求。（激活重做日志归档时会强制执行这些要求。）：

-   目录必须存在。目录不是由重做日志归档进程创建的。否则，将返回以下错误：

    ERROR 3844 (HY000): 重做日志归档目录'*`目录路径1`*' 不存在或不是目录

-   目录不能是全世界可访问的。这是为了防止重做日志数据暴露给系统上的未授权用户。否则，将返回以下错误：

    ERROR 3846 (HY000): 重做日志存档目录'*`目录路径1`*' 可供所有操作系统用户访问

-   目录不能是那些定义的[`数据目录`](server-system-variables.html#sysvar_datadir),[`innodb_data_home_dir`](innodb-parameters.html#sysvar_innodb_data_home_dir),[`innodb_directories`](innodb-parameters.html#sysvar_innodb_directories),[`innodb_log_group_home_dir`](innodb-parameters.html#sysvar_innodb_log_group_home_dir),[`innodb_temp_tablespaces_dir`](innodb-parameters.html#sysvar_innodb_temp_tablespaces_dir),[`innodb_tmpdir`](innodb-parameters.html#sysvar_innodb_tmpdir) [`innodb_undo_directory`](innodb-parameters.html#sysvar_innodb_undo_directory)， 要么[`secure_file_priv`](server-system-variables.html#sysvar_secure_file_priv), 也不能是这些目录的父目录或子目录。否则，会返回类似以下的错误：

    ERROR 3845 (HY000): 重做日志归档目录'*`目录路径1`*' 在服务器目录 'datadir' 中、之下或之上 - '*`/path/to/data_directory`*'

    当支持重做日志归档的备份实用程序启动备份时，备份实用程序通过调用`innodb_redo_log_archive_start()`功能。

    如果您没有使用支持重做日志归档的备份实用程序，也可以手动激活重做日志归档，如下所示：


```
mysql> SELECT innodb_redo_log_archive_start('label', 'subdir');
+------------------------------------------+
| innodb_redo_log_archive_start('label') |
+------------------------------------------+
| 0                                        |
+------------------------------------------+
```

要么：

```
mysql> DO innodb_redo_log_archive_start('label', 'subdir');
Query OK, 0 rows affected (0.09 sec)
```

笔记

激活重做日志归档的 MySQL 会话（使用`innodb_redo_log_archive_start()`) 必须在归档期间保持打开状态。同一会话必须停用重做日志归档（使用`innodb_redo_log_archive_stop()`）。如果在显式停用重做日志归档之前终止会话，则服务器会隐式停用重做日志归档并删除重做日志归档文件。

在哪里*`标签`*是由定义的标签[`innodb_redo_log_archive_dirs`](innodb-parameters.html#sysvar_innodb_redo_log_archive_dirs);`子目录`是一个可选参数，用于指定由标识的目录的子目录*`标签`*用于保存存档文件；它必须是一个简单的目录名称（没有斜杠 (/)、反斜杠 (\\) 或冒号 (:) 是允许的）。`子目录`可以为空、null，也可以省略。

只有具有[`INNODB_REDO_LOG_ARCHIVE`](privileges-provided.html#priv_innodb-redo-log-archive)权限可以通过调用激活重做日志归档`innodb_redo_log_archive_start()`，或使用停用它`innodb_redo_log_archive_stop()`.运行备份实用程序的 MySQL 用户或手动激活和停用重做日志归档的 MySQL 用户必须具有此权限。

重做日志归档文件路径是`*`directory_identified_by_label`*/[*`子目录`*/]档案。*`服务器UUID`*.000001.log`， 在哪里`*`directory_identified_by_label`*`是由`*`标签`*`论据`innodb_redo_log_archive_start()`.`*`子目录`*`是用于的可选参数`innodb_redo_log_archive_start()`.

例如，重做日志归档文件的完整路径和名称类似于以下内容：

```
/directory_path/subdirectory/archive.e71a47dc-61f8-11e9-a3cb-080027154b4d.000001.log
```

备份实用程序完成复制后`InnoDB`数据文件，它通过调用`innodb_redo_log_archive_stop()`功能。

如果您没有使用支持重做日志归档的备份实用程序，也可以手动停用重做日志归档，如下所示：

```
mysql> SELECT innodb_redo_log_archive_stop();
+--------------------------------+
| innodb_redo_log_archive_stop() |
+--------------------------------+
| 0                              |
+--------------------------------+
```

要么：

```
mysql> DO innodb_redo_log_archive_stop();
Query OK, 0 rows affected (0.01 sec)
```

停止功能成功完成后，备份实用程序从归档文件中查找重做日志数据的相关部分并将其复制到备份中。

在备份实用程序完成复制重做日志数据并且不再需要重做日志归档文件后，它会删除归档文件。

在正常情况下，删除存档文件是备份实用程序的责任。但是，如果重做日志归档操作之前意外退出`innodb_redo_log_archive_stop()`被调用时，MySQL 服务器会删除该文件。

##### 性能注意事项

由于额外的写入活动，激活重做日志归档通常会带来较小的性能成本。

在Unix和类似Unix的操作系统上，如果没有持续的高更新率，对性能的影响通常很小。在Windows上，假设相同的情况下，性能影响通常稍高一些。

如果更新率持续较高，且重做日志存档文件与重做日志文件位于同一存储介质上，则由于复杂的写入活动，性能影响可能会更大。

如果更新率持续较高，且重做日志存档文件位于比重做日志文件慢的存储介质上，则性能会受到任意影响。

写入重做日志存档文件不会妨碍正常的事务性日志记录，除非重做日志存档文件存储介质的运行速度比重做日志文件存储介质慢得多，并且存在大量积压的持久重做日志块等待写入重做日志存档文件。在这种情况下，事务性日志记录速率降低到可以由重做日志存档文件所在的较慢存储介质管理的级别。

#### 禁用重做日志记录

从MySQL 8.0.21开始，您可以使用[`更改实例禁用INNODB重做日志`](alter-instance.html)陈述此功能用于将数据加载到新的MySQL实例中。禁用重做日志通过避免重做日志写入和双写缓冲来加速数据加载。

警告

此功能仅用于将数据加载到新的MySQL实例中。*不要在生产系统上禁用重做日志记录。*允许在禁用重做日志记录时关闭并重新启动服务器，但在禁用重做日志记录时意外停止服务器可能会导致数据丢失和实例损坏。

在禁用重做日志记录时，服务器意外停止后，尝试重新启动服务器被拒绝，错误如下：

```
[ERROR] [MY-013598] [InnoDB] Server was killed when Innodb Redo
logging was disabled. Data files could be corrupt. You can try
to restart the database with innodb_force_recovery=6
```

在这种情况下，初始化一个新的MySQL实例，然后再次启动数据加载过程。

这个[`INNODB_重做_日志_启用`](privileges-provided.html#priv_innodb-redo-log-enable)启用和禁用重做日志记录需要特权。

这个[`Innodb_重做_日志_已启用`](server-status-variables.html#statvar_Innodb_redo_log_enabled)状态变量允许监视重做日志记录状态。

禁用重做日志记录时，不允许克隆操作和重做日志存档，反之亦然。

一[`更改实例[ENABLE | DISABLE]INNODB重做日志`](alter-instance.html)操作需要独占备份元数据锁，这会阻止其他[`改变实例`](alter-instance.html)操作不能同时执行。另外[`改变实例`](alter-instance.html)操作必须等待锁释放后才能执行。

下面的过程演示如何在将数据加载到新的MySQL实例时禁用重做日志记录。

1.  在新的MySQL实例上，授予[`INNODB_重做_日志_启用`](privileges-provided.html#priv_innodb-redo-log-enable)负责禁用重做日志记录的用户帐户的权限。

    ```
    mysql> GRANT INNODB_REDO_LOG_ENABLE ON *.* to 'data_load_admin';
    ```

2.  作为`数据加载管理`用户，禁用重做日志记录：

    ```
    mysql> ALTER INSTANCE DISABLE INNODB REDO_LOG;
    ```

3.  检查[`Innodb_重做_日志_已启用`](server-status-variables.html#statvar_Innodb_redo_log_enabled)状态变量，以确保禁用重做日志记录。

    ```
    mysql> SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_enabled';
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | Innodb_redo_log_enabled | OFF   |
    +-------------------------+-------+
    ```

4.  运行数据加载操作。

5.  作为`数据加载管理`用户，在数据加载操作完成后启用重做日志记录：

    ```
    mysql> ALTER INSTANCE ENABLE INNODB REDO_LOG;
    ```

6.  检查[`Innodb_重做_日志_已启用`](server-status-variables.html#statvar_Innodb_redo_log_enabled)状态变量，以确保启用重做日志记录。

    ```
    mysql> SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_enabled';
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | Innodb_redo_log_enabled | ON    |
    +-------------------------+-------+
    ```

#### 相关话题

-   [重做日志文件配置](innodb-init-startup-configuration.html#innodb-startup-log-file-configuration)

-   [第8.5.4节，“优化InnoDB重做日志”](optimizing-innodb-logging.html)

-   [重做日志加密](innodb-data-encryption.html#innodb-data-encryption-redo-log)
