重做日志是一个磁盘 기반的数据结构,用于崩溃恢复中纠正未完成事务写入的数据。在正常操作期间,重做日志编码来自SQL语句或低级API调用的表数据更改请求。在意外关闭之前未完成更新数据文件的修改将在初始化和接受连接之前自动重放。有关重做日志在崩溃恢复中的角色,请参阅第 17.18.2 节,“InnoDB 恢复”。
重做日志在磁盘上由重做日志文件物理表示。写入重做日志文件的数据以记录受影响的形式编码,统称为重做。重做日志文件中的数据通过递增的LSN值表示。随着数据修改的发生,重做日志数据被追加,而最旧的数据随着检查点的进度被截断。
与重做日志相关的信息和过程在以下主题中描述:
系统变量 innodb_redo_log_capacity
控制重做日志文件占用的磁盘空间。你可以在启动时在选项文件中设置该变量,或者在运行时使用 SET GLOBAL
语句;例如,以下语句将重做日志容量设置为 8GB:
SET GLOBAL innodb_redo_log_capacity = 8589934592;
在运行时设置时,配置更改立即生效,但可能需要一些时间来完全实现。如果重做日志文件占用的空间小于指定值,脏页将从缓冲池中刷新到表空间数据文件中,逐渐增加重做日志文件占用的磁盘空间。如果重做日志文件占用的空间大于指定值,脏页将更积极地刷新到表空间数据文件中,逐渐减少重做日志文件占用的磁盘空间。
变量 innodb_redo_log_capacity
取代了 innodb_log_files_in_group
和 innodb_log_file_size
变量,这些变量已弃用。当 innodb_redo_log_capacity
设置时,innodb_log_files_in_group
和 innodb_log_file_size
设置将被忽略;否则,这些设置将用于计算 innodb_redo_log_capacity
设置 (innodb_log_files_in_group
* innodb_log_file_size
= innodb_redo_log_capacity
)。如果没有设置这些变量,重做日志容量将设置为 innodb_redo_log_capacity
的默认值,即 104857600 字节(100MB)。重做日志容量的最大值为 128GB。
重做日志文件位于数据目录中的 #innodb_redo
目录中,除非通过 innodb_log_group_home_dir
变量指定了不同的目录。如果定义了 innodb_log_group_home_dir
,重做日志文件将位于该目录中的 #innodb_redo
目录中。有两种类型的重做日志文件:普通重做日志文件和备用重做日志文件。普通重做日志文件是当前使用的文件。备用重做日志文件是等待使用的文件。InnoDB
尝试维护 32 个重做日志文件,总大小等于 innodb_redo_log_capacity
的 1/32;然而,文件大小可能在修改 innodb_redo_log_capacity
设置后一段时间内不同。
重做日志文件使用 #ib_redo
命名约定,其中 N
N
是重做日志文件号。备用重做日志文件以 _tmp
后缀表示。以下示例显示了 #innodb_redo
目录中的重做日志文件,其中有 21 个活动重做日志文件和 11 个备用重做日志文件,编号顺序排列。
'#ib_redo582' '#ib_redo590' '#ib_redo598' '#ib_redo606_tmp'
'#ib_redo583' '#ib_redo591' '#ib_redo599' '#ib_redo607_tmp'
'#ib_redo584' '#ib_redo592' '#ib_redo600' '#ib_redo608_tmp'
'#ib_redo585' '#ib_redo593' '#ib_redo601' '#ib_redo609_tmp'
'#ib_redo586' '#ib_redo594' '#ib_redo602' '#ib_redo610_tmp'
'#ib_redo587' '#ib_redo595' '#ib_redo603_tmp' '#ib_redo611_tmp'
'#ib_redo588' '#ib_redo596' '#ib_redo604_tmp' '#ib_redo612_tmp'
'#ib_redo589' '#ib_redo597' '#ib_redo605_tmp' '#ib_redo613_tmp'
每个普通重做日志文件都与特定的 LSN 值范围相关;例如,以下查询显示了活动重做日志文件的 START_LSN
和 END_LSN
值:
mysql> SELECT FILE_NAME, START_LSN, END_LSN FROM performance_schema.innodb_redo_log_files;
+----------------------------+--------------+--------------+
| FILE_NAME | START_LSN | END_LSN |
+----------------------------+--------------+--------------+
| ./#innodb_redo/#ib_redo582 | 117654982144 | 117658256896 |
| ./#innodb_redo/#ib_redo583 | 117658256896 | 117661531648 |
| ./#innodb_redo/#ib_redo584 | 117661531648 | 117664806400 |
| ./#innodb_redo/#ib_redo585 | 117664806400 | 117668081152 |
| ./#innodb_redo/#ib_redo586 | 117668081152 | 117671355904 |
| ./#innodb_redo/#ib_redo587 | 117671355904 | 117674630656 |
| ./#innodb_redo/#ib_redo588 | 117674630656 | 117677905408 |
| ./#innodb_redo/#ib_redo589 | 117677905408 | 117681180160 |
| ./#innodb_redo/#ib_redo590 | 117681180160 | 117684454912 |
| ./#innodb_redo/#ib_redo591 | 117684454912 | 117687729664 |
| ./#innodb_redo/#ib_redo592 | 117687729664 | 117691004416 |
| ./#innodb_redo/#ib_redo593 | 117691004416 | 117694279168 |
| ./#innodb_redo/#ib_redo594 | 117694279168 | 117697553920 |
| ./#innodb_redo/#ib_redo595 | 117697553920 | 117700828672 |
| ./#innodb_redo/#ib_redo596 | 117700828672 | 117704103424 |
| ./#innodb_redo/#ib_redo597 | 117704103424 | 117707378176 |
| ./#innodb_redo/#ib_redo598 | 117707378176 | 117710652928 |
| ./#innodb_redo/#ib_redo599 | 117710652928 | 117713927680 |
| ./#innodb_redo/#ib_redo600 | 117713927680 | 117717202432 |
| ./#innodb_redo/#ib_redo601 | 117717202432 | 117720477184 |
| ./#innodb_redo/#ib_redo602 | 117720477184 | 117723751936 |
+----------------------------+--------------+--------------+
在检查点时,InnoDB
将检查点 LSN 存储在包含该 LSN 的文件头中。在恢复期间,所有重做日志文件都会被检查,恢复将从最新的检查点 LSN 开始。
提供了多个状态变量来监控重做日志和重做日志容量调整操作;例如,您可以查询 Innodb_redo_log_resize_status
以查看调整操作的状态:
mysql> SHOW STATUS LIKE 'Innodb_redo_log_resize_status';
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| Innodb_redo_log_resize_status | OK |
+-------------------------------+-------+
状态变量 Innodb_redo_log_capacity_resized
显示当前重做日志容量限制:
mysql> SHOW STATUS LIKE 'Innodb_redo_log_capacity_resized';
+----------------------------------+-----------+
| Variable_name | Value |
+----------------------------------+-----------+
| Innodb_redo_log_capacity_resized | 104857600 |
+----------------------------------+-----------+
其他适用的状态变量包括:
请参阅状态变量描述以获取更多信息。
您可以通过查询 innodb_redo_log_files
Performance Schema 表来查看活动重做日志文件的信息。以下查询从表的所有列中检索数据:
SELECT FILE_ID, START_LSN, END_LSN, SIZE_IN_BYTES, IS_FULL, CONSUMER_LEVEL
FROM performance_schema.innodb_redo_log_files;
当 innodb_dedicated_server
启用时,InnoDB
将自动配置某些 InnoDB
参数,包括重做日志容量。自动配置旨在为专门用于 MySQL 的服务器,MySQL 服务器可以使用所有可用的系统资源。有关更多信息,请参阅 第 17.8.12 节,“为专门的 MySQL 服务器启用自动配置”。
备份实用程序可能无法跟上重做日志生成的速度,而导致重做日志记录丢失。这种情况通常发生在 MySQL 服务器活动期间备份操作进行时,重做日志文件存储介质的速度快于备份存储介质。重做日志归档功能解决了这个问题,通过将重做日志记录顺序写入归档文件,以便备份实用程序可以从归档文件中复制重做日志记录,从而避免数据丢失。
如果服务器配置了重做日志归档,MySQL Enterprise Backup,随 MySQL Enterprise Edition 一起提供,将使用重做日志归档功能备份 MySQL 服务器。
在服务器上启用重做日志归档需要设置innodb_redo_log_archive_dirs
系统变量的值。该值指定为以分号分隔的重做日志归档目录列表。每个
对通过冒号(标签:目录
:
)分隔。例如:
mysql> SET GLOBAL innodb_redo_log_archive_dirs='label1:directory_path1[;label2:directory_path2;…]';
该标签
是归档目录的任意标识符。它可以是任何字符串,除了冒号(:)外,不允许使用。空标签也是允许的,但仍需要冒号(:)。目录路径
必须指定。选择的目录必须在启用重做日志归档时存在,否则将返回错误。
必须在激活重做日志归档之前配置innodb_redo_log_archive_dirs
变量。默认值为NULL
您指定的归档目录必须满足以下要求。(这些要求是在激活重做日志归档时强制执行的。)
-
目录必须存在。目录不是由重做日志归档过程创建的。否则,将返回以下错误:
错误 3844 (HY000): 重做日志归档目录 '
目录路径1
' 不存在或不是目录 -
目录不得是世界可访问的。这是为了防止重做日志数据被系统上的未经授权用户访问。否则,将返回以下错误:
错误 3846 (HY000): 重做日志归档目录 '
目录路径1
' 对所有 OS 用户都是可访问的 -
目录不能是由
datadir
、innodb_data_home_dir
、innodb_directories
、innodb_log_group_home_dir
、innodb_temp_tablespaces_dir
、innodb_tmpdir
或innodb_undo_directory
或secure_file_priv
定义的目录,也不能是这些目录的父目录或子目录。否则,将返回类似以下的错误:错误 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
定义的标签;子目录
是一个可选参数,用于指定标识为 标签
的目录的子目录以保存归档文件;它必须是一个简单的目录名称(不允许使用斜杠 (/)、反斜杠 (\) 或冒号 (:))。子目录
可以为空、null 或省略。
只有具有
INNODB_REDO_LOG_ARCHIVE
权限的用户可以通过调用 innodb_redo_log_archive_start()
激活重做日志归档,或者使用 innodb_redo_log_archive_stop()
停用它。运行备份实用程序或手动激活和停用重做日志归档的 MySQL 用户必须具有该权限。
重做日志存档文件路径是
,其中 directory_identified_by_label
/[subdir
/]archive.serverUUID
.000001.log
是存档目录,标识为 directory_identified_by_label
参数的 label
innodb_redo_log_archive_start()
。
是可选参数,用于 subdir
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-like 操作系统上,性能影响通常很小,假设没有持续的高更新率。在 Windows 上,性能影响通常较高,假设相同。
如果存在持续的高更新率,并且重做日志存档文件位于与重做日志文件相同的存储介质上,性能影响可能会更大,因为写活动会叠加。
如果存在持续的高更新率,并且重做日志存档文件位于比重做日志文件慢的存储介质上,性能将受到任意影响。
写入重做日志存档文件不会阻碍正常的事务日志记录,除非重做日志存档文件存储介质的速度远远慢于重做日志文件存储介质,并且存在大量的持久化重做日志块等待写入重做日志存档文件。在这种情况下,事务日志记录率将降低到可以由慢速存储介质管理的水平。
您可以使用 ALTER INSTANCE DISABLE INNODB REDO_LOG
语句禁用重做日志记录。这项功能旨在加载数据到新的 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_REDO_LOG_ENABLE
权限来启用和禁用重做日志记录。
可以使用 Innodb_redo_log_enabled
状态变量来监控重做日志记录状态。
克隆操作和重做日志存档不能在禁用重做日志记录时进行,反之亦然。
一个 ALTER INSTANCE [ENABLE|DISABLE] INNODB REDO_LOG
操作需要独占备份元数据锁,这将阻止其他 ALTER INSTANCE
操作同时执行。其他 ALTER INSTANCE
操作必须等待锁释放后执行。
以下过程演示了如何在加载数据到新的 MySQL 实例时禁用重做日志记录。
-
在新的 MySQL 实例上,授予负责禁用 redo 日志记录的用户账户
INNODB_REDO_LOG_ENABLE
权限。mysql> GRANT INNODB_REDO_LOG_ENABLE ON *.* to 'data_load_admin';
-
作为
data_load_admin
用户,禁用 redo 日志记录:mysql> ALTER INSTANCE DISABLE INNODB REDO_LOG;
-
检查
Innodb_redo_log_enabled
状态变量,以确保 redo 日志记录已禁用。mysql> SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_enabled'; +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | Innodb_redo_log_enabled | OFF | +-------------------------+-------+
-
运行数据加载操作。
-
作为
data_load_admin
用户,在数据加载操作完成后启用 redo 日志记录:mysql> ALTER INSTANCE ENABLE INNODB REDO_LOG;
-
检查
Innodb_redo_log_enabled
状态变量,以确保 redo 日志记录已启用。mysql> SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_enabled'; +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | Innodb_redo_log_enabled | ON | +-------------------------+-------+