Documentation Home

15.6.3.4 撤消表空间

撤消表空间包含撤消日志,这些记录是包含有关如何撤消事务对聚集索引记录的最新更改的信息的记录集合。

撤消表空间在本节的以下主题下进行了描述:

默认撤消表空间

初始化 MySQL 实例时会创建两个默认的撤消表空间。默认撤消表空间是在初始化时创建的,以便为回滚段提供位置,回滚段在接受 SQL 语句之前必须存在。至少需要两个撤消表空间来支持撤消表空间的自动截断。请参阅 截断撤消表空间

innodb_undo_directory 默认撤消表空间是在变量 定义的位置创建的。如果该 innodb_undo_directory变量未定义,则在数据目录中创建默认的撤消表空间。默认撤消表空间数据文件名为 undo_001undo_002。数据字典中定义的对应undo表空间名称为innodb_undo_001innodb_undo_002

从 MySQL 8.0.14 开始,可以在运行时使用 SQL 创建额外的撤消表空间。请参阅 添加撤消表空间

撤消表空间大小

在 MySQL 8.0.23 之前,undo 表空间的初始大小取决于该innodb_page_size 值。对于默认的 16KB 页面大小,初始撤消表空间文件大小为 10MiB。对于 4KB、8KB、32KB 和 64KB 页面大小,初始撤消表空间文件大小分别为 7MiB、8MiB、20MiB 和 40MiB。从 MySQL 8.0.23 开始,初始撤消表空间大小通常为 16MiB。当通过截断操作创建新的撤消表空间时,初始大小可能会有所不同。在这种情况下,如果文件扩展名大于 16MB,并且前一个文件扩展名出现在最后一秒内,则新的撤消表空间将创建为 innodb_max_undo_log_size 变量定义的大小的四分之一。

在 MySQL 8.0.23 之前,撤消表空间一次扩展四个区。从 MySQL 8.0.23 开始,撤消表空间至少扩展了 16MB。为应对急剧增长,如果前一个文件扩展名发生时间小于 0.1 秒,则文件扩展名大小会加倍。扩展大小加倍可能会发生多次,最大为 256MB。如果前一个文件扩展名早于 0.1 秒出现,则扩展名大小将减少一半,这也可能出现多次,最小为 16MB。如果该 AUTOEXTEND_SIZE选项是为撤消表空间定义的,则它会扩展 AUTOEXTEND_SIZE设置和由上述逻辑确定的扩展大小。有关该AUTOEXTEND_SIZE选项的信息,请参阅 第 15.6.3.9 节,“表空间 AUTOEXTEND_SIZE 配置”

添加撤消表空间

因为在长时间运行的事务中撤消日志会变得很大,创建额外的撤消表空间有助于防止单个撤消表空间变得太大。从 MySQL 8.0.14 开始,可以在运行时使用 CREATE UNDO TABLESPACE语法创建额外的撤消表空间。

CREATE UNDO TABLESPACE tablespace_name ADD DATAFILE 'file_name.ibu';

撤消表空间文件名必须有 .ibu扩展名。定义undo表空间文件名时不允许指定相对路径。允许使用完全限定的路径,但该路径必须为InnoDB. 已知路径是由 innodb_directories变量定义的路径。建议使用唯一的撤消表空间文件名,以避免在移动或克隆数据时发生潜在的文件名冲突。

笔记

在复制环境中,源和每个副本必须有自己的撤消表空间文件目录。将撤消表空间文件的创建复制到公共目录会导致文件名冲突。

在启动时, innodb_directories将扫描变量定义的目录以查找撤消表空间文件。(扫描还遍历子目录。)由 、 和 变量定义的目录 innodb_data_home_dirinnodb_undo_directory自动 datadir附加到 innodb_directories值,而不管该 innodb_directories变量是否明确定义。因此,撤消表空间可以驻留在由任何这些变量定义的路径中。

如果撤消表空间文件名不包含路径,则在 innodb_undo_directory变量定义的目录中创建撤消表空间。如果该变量未定义,则在数据目录中创建撤消表空间。

笔记

InnoDB恢复过程要求撤消表空间文件驻留在已知目录中 。必须在重做恢复之前和打开其他数据文件之前发现并打开撤消表空间文件,以允许回滚未提交的事务和数据字典更改。无法使用恢复前未找到的撤消表空间,这会导致数据库不一致。如果未找到数据字典已知的撤消表空间,则会在启动时报告一条错误消息。已知目录要求还支持撤消表空间可移植性。请参阅 移动撤消表空间

要在相对于数据目录的路径中创建undo 表空间,请将 innodb_undo_directory变量设置为相对路径,并仅在创建undo 表空间时指定文件名。

要查看撤消表空间名称和路径,请查询 INFORMATION_SCHEMA.FILES

SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES
  WHERE FILE_TYPE LIKE 'UNDO LOG';

一个 MySQL 实例最多支持 127 个 undo 表空间,包括 MySQL 实例初始化时创建的两个默认的 undo 表空间。

笔记

在 MySQL 8.0.14 之前,额外的撤消表空间是通过配置 innodb_undo_tablespaces 启动变量来创建的。从 MySQL 8.0.14 开始,此变量已弃用且不再可配置。

在 MySQL 8.0.14 之前,增加 innodb_undo_tablespaces 设置会创建指定数量的撤消表空间并将它们添加到活动撤消表空间列表中。减小innodb_undo_tablespaces 设置将从活动撤消表空间列表中删除撤消表空间。从活动列表中删除的撤消表空间保持活动状态,直到它们不再被现有事务使用。该 innodb_undo_tablespaces 变量可以在运行时使用 SET 语句配置或在配置文件中定义。

在 MySQL 8.0.14 之前,无法删除已停用的撤消表空间。缓慢关闭后可以手动删除撤消表空间文件,但不建议这样做,因为如果关闭服务器时存在打开的事务,则停用的撤消表空间可能会在服务器重新启动后的一段时间内包含活动的撤消日志。从 MySQL 8.0.14 开始,可以使用 DROP UNDO TABALESPACE语法删除撤消表空间。请参阅 删除撤消表空间

删除撤消表空间

从 MySQL 8.0.14 开始,使用 CREATE UNDO TABLESPACE语法创建的撤消表空间可以在运行时使用 DROP UNDO TABALESPACE语法删除。

撤消表空间在被删除之前必须是空的。要清空撤消表空间,必须首先使用 ALTER UNDO TABLESPACE语法将撤消表空间标记为不活动,以便该表空间不再用于将回滚段分配给新事务。

ALTER UNDO TABLESPACE tablespace_name SET INACTIVE;

在撤消表空间被标记为不活动后,允许当前使用撤消表空间中的回滚段的事务完成,就像在这些事务完成之前开始的任何事务一样。事务完成后,清除系统释放撤消表空间中的回滚段,撤消表空间被截断为其初始大小。(截断撤消表空间时使用相同的过程。请参阅截断撤消表空间。)一旦撤消表空间为空,就可以将其删除。

DROP UNDO TABLESPACE tablespace_name;
笔记

或者,撤消表空间可以保留为空状态,并在需要时通过发出 语句重新激活。 ALTER UNDO TABLESPACE tablespace_name SET ACTIVE

可以通过查询 INFORMATION_SCHEMA.INNODB_TABLESPACES 表来监视撤消表空间的状态。

SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
  WHERE NAME LIKE 'tablespace_name';

状态表示撤消表空间中的inactive回滚段不再被新事务使用。状态表示empty撤消表空间为空并准备好被删除,或者准备好使用 语句再次激活。尝试删除非空的撤消表空间会返回错误。 ALTER UNDO TABLESPACE tablespace_name SET ACTIVE

MySQL实例初始化时创建的默认undo表空间(innodb_undo_001innodb_undo_002)不能被删除。但是,可以使用 语句使它们处于非活动状态。在可以使默认撤消表空间处于非活动状态之前,必须有一个撤消表空间来取而代之。始终需要至少两个活动的撤消表空间来支持撤消表空间的自动截断。 ALTER UNDO TABLESPACE tablespace_name SET INACTIVE

移动撤消表空间

CREATE UNDO TABLESPACE可以在服务器离线时将 使用语法创建的撤消表空间 移动到任何已知目录。已知目录是由 innodb_directories变量定义的目录。由 innodb_data_home_dirinnodb_undo_directory和 定义的目录datadir会自动附加到 innodb_directories值,而不管该 innodb_directories变量是否明确定义。这些目录及其子目录在启动时会被扫描以查找撤消表空间文件。移动到任何这些目录的撤消表空间文件在启动时被发现,并假定为已移动的撤消表空间。

初始化 MySQL 实例时创建的默认撤消表空间(innodb_undo_001innodb_undo_002)必须驻留在innodb_undo_directory 变量定义的目录中。如果该 innodb_undo_directory变量未定义,则默认撤消表空间驻留在数据目录中。如果在服务器脱机时移动默认撤消表空间,则必须使用 innodb_undo_directory配置到新目录的变量启动服务器。

撤消日志的 I/O 模式使撤消表空间成为SSD存储 的理想选择。

配置回滚段数

innodb_rollback_segments 变量定义 分配给每个撤消表空间和全局临时表空间的回滚段数。innodb_rollback_segments 变量可以在启动时或服务器运行时配置。

默认设置为 innodb_rollback_segments128,这也是最大值。有关回滚段支持的事务数的信息,请参阅 第 15.6.6 节,“撤消日志”

截断撤消表空间

有两种截断撤消表空间的方法,可以单独使用或组合使用来管理撤消表空间大小。一种方法是自动化的,使用配置变量启用。另一种方法是手动的,使用 SQL 语句执行。

自动化方法不需要监视撤消表空间大小,一旦启用,它会执行撤消表空间的停用、截断和重新激活,而无需手动干预。如果您想控制撤消表空间何时脱机以进行截断,则手动截断方法可能更可取。例如,您可能希望避免在工作负载高峰期截断撤消表空间。

自动截断

undo 表空间的自动截断需要至少两个活动的 undo 表空间,这可确保一个 undo 表空间保持活动状态,而另一个处于脱机状态以进行截断。默认情况下,MySQL实例初始化时会创建两个undo表空间。

要自动截断撤消表空间,请启用该 innodb_undo_log_truncate 变量。例如:

mysql> SET GLOBAL innodb_undo_log_truncate=ON;

启用该 innodb_undo_log_truncate 变量后,超过该变量定义的大小限制的撤消表空间将 innodb_max_undo_log_size 被截断。该 innodb_max_undo_log_size 变量是动态的,默认值为 1073741824 字节 (1024 MiB)。

mysql> SELECT @@innodb_max_undo_log_size;
+----------------------------+
| @@innodb_max_undo_log_size |
+----------------------------+
|                 1073741824 |
+----------------------------+

innodb_undo_log_truncate 启用变量 时 :

  1. 超过设置的默认和用户定义的撤消表空间 innodb_max_undo_log_size 被标记为截断。选择要截断的撤消表空间以循环方式执行,以避免每次都截断相同的撤消表空间。

  2. 驻留在所选撤消表空间中的回滚段将变为非活动状态,以便它们不会分配给新事务。允许当前正在使用回滚段的现有事务完成。

  3. 清除系统通过释放不再使用 的撤销日志来清空回滚段。

  4. 在撤消表空间中的所有回滚段都被释放后,截断操作运行并将撤消表空间截断为其初始大小。

    由于在操作完成后立即使用,截断操作后撤消表空间的大小可能大于初始大小。

    innodb_undo_directory 变量定义默认撤消表空间文件的位置。如果该 innodb_undo_directory 变量未定义,则默认撤消表空间驻留在数据目录中。CREATE UNDO TABLESPACE可以通过查询表来确定 所有撤消表空间文件的位置,包括使用语法创建的用户定义的撤消表空间 INFORMATION_SCHEMA.FILES

    SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE LIKE 'UNDO LOG';
  5. 回滚段被重新激活,以便它们可以分配给新的事务。

手动截断

手动截断撤消表空间需要至少三个活动的撤消表空间。始终需要两个活动的撤消表空间以支持启用自动截断的可能性。至少三个撤消表空间可以满足此要求,同时允许手动使撤消表空间脱机。

要手动启动撤消表空间的截断,请通过发出以下语句停用撤消表空间:

ALTER UNDO TABLESPACE tablespace_name SET INACTIVE;

在撤消表空间被标记为不活动后,允许当前使用撤消表空间中的回滚段的事务完成,就像在这些事务完成之前开始的任何事务一样。事务完成后,purge 系统释放 undo 表空间中的回滚段,undo 表空间被截断为初始大小,undo 表空间状态从 inactive变为empty

笔记

当语句停用撤消表空间时,清除线程会在下一次机会时查找该撤消表空间。一旦找到撤消表空间并将其标记为截断,清除线程就会以更高的频率返回以快速清空并截断撤消表空间。 ALTER UNDO TABLESPACE tablespace_name SET INACTIVE

要检查撤消表空间的状态,请查询该 INFORMATION_SCHEMA.INNODB_TABLESPACES 表。

SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
  WHERE NAME LIKE 'tablespace_name';

一旦撤消表空间处于某个empty 状态,就可以通过发出以下语句将其重新激活:

ALTER UNDO TABLESPACE tablespace_name SET ACTIVE;

处于状态的撤消表空间empty也可以被删除。请参阅删除撤消表空间

加快撤消表空间的自动截断

清除线程负责清空和截断撤消表空间。默认情况下,清除线程查找撤消表空间以每调用清除 128 次截断一次。清除线程查找要截断的撤消表空间的频率由 innodb_purge_rseg_truncate_frequency 变量控制,该变量的默认设置为 128。

mysql> SELECT @@innodb_purge_rseg_truncate_frequency;
+----------------------------------------+
| @@innodb_purge_rseg_truncate_frequency |
+----------------------------------------+
|                                    128 |
+----------------------------------------+

要增加频率,请减小 innodb_purge_rseg_truncate_frequency 设置。例如,要让清除线程每 32 次调用清除一次查找撤消表空间,请设置 innodb_purge_rseg_truncate_frequency 为 32。

mysql> SET GLOBAL innodb_purge_rseg_truncate_frequency=32;
截断撤消表空间文件的性能影响

当撤消表空间被截断时,撤消表空间中的回滚段将被停用。其他撤消表空间中的活动回滚段承担整个系统负载的责任,这可能会导致轻微的性能下降。性能受影响的程度取决于许多因素:

  • 撤消表空间数

  • 撤消日志数

  • 撤消表空间大小

  • I/O 子系统的速度

  • 现有的长期运行的事务

  • 系统负载

避免潜在性能影响的最简单方法是增加撤消表空间的数量。

监视撤消表空间截断

从 MySQL 8.0.16 开始,undo提供 purge了子系统计数器来监视与撤消日志截断相关的后台活动。计数器名称和描述,请查询该 INFORMATION_SCHEMA.INNODB_METRICS 表。

SELECT NAME, SUBSYSTEM, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%truncate%';

有关启用计数器和查询计数器数据的信息,请参阅 第 15.15.6 节,“InnoDB INFORMATION_SCHEMA 指标表”

撤消表空间截断限制

从 MySQL 8.0.21 开始,检查点之间对同一撤消表空间的截断操作数限制为 64。该限制可防止因撤消表空间截断操作次数过多而导致的潜在问题,如果 innodb_max_undo_log_size设置太低,可能会发生这种情况例如,繁忙的系统。如果超过限制,撤消表空间仍然可以处于非活动状态,但直到下一个检查点之后才会被截断。在 MySQL 8.0.22 中,限制从 64 提高到 50,000。

撤消表空间截断恢复

撤消表空间截断操作会在服务器日志目录中创建一个临时 文件。该日志目录由. 如果在截断操作期间发生系统故障,临时日志文件允许启动过程识别被截断的撤消表空间并继续操作。 undo_space_number_trunc.loginnodb_log_group_home_dir

撤消表空间状态变量

以下状态变量允许跟踪撤消表空间的总数、隐式(InnoDB创建的)撤消表空间、显式(用户创建的)撤消表空间和活动撤消表空间的数量:

mysql> SHOW STATUS LIKE 'Innodb_undo_tablespaces%';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| Innodb_undo_tablespaces_total    | 2     |
| Innodb_undo_tablespaces_implicit | 2     |
| Innodb_undo_tablespaces_explicit | 0     |
| Innodb_undo_tablespaces_active   | 2     |
+----------------------------------+-------+

有关状态变量的描述,请参阅 第 5.1.10 节,“服务器状态变量”