撤消表空间包含撤消日志,这些日志是记录的集合,其中包含有关如何撤消事务对聚集索引记录的最新更改的信息。
本节以下主题介绍了撤消表空间
初始化 MySQL 实例时,会创建两个默认撤消表空间。默认撤消表空间在初始化时创建,用于为在接受 SQL 语句之前必须存在的回滚段提供位置。至少需要两个撤消表空间才能支持撤消表空间的自动截断。请参见 截断撤消表空间。
默认撤消表空间在 innodb_undo_directory
变量定义的位置创建。如果未定义 innodb_undo_directory
变量,则会在数据目录中创建默认撤消表空间。默认撤消表空间数据文件名为 undo_001
和 undo_002
。数据字典中定义的相应撤消表空间名称为 innodb_undo_001
和 innodb_undo_002
。
可以使用 SQL 语句在运行时创建其他撤消表空间。请参见 添加撤消表空间。
初始撤消表空间大小通常为 16MiB。当通过截断操作创建新的撤消表空间时,初始大小可能会有所不同。在这种情况下,如果文件扩展大小大于 16MB,并且上一次文件扩展发生在最后一秒内,则新撤消表空间的大小将创建为 innodb_max_undo_log_size
变量定义的四分之一大小。
撤消表空间以 16MB 为单位进行扩展。为了处理激进的增长,如果之前的文件扩展发生在不到 0.1 秒之前,则文件扩展大小将翻倍。扩展大小的翻倍可以发生多次,最大可达 256MB。如果之前的文件扩展发生在 0.1 秒之前,则扩展大小会减半,这也可以发生多次,最小为 16MB。如果为撤消表空间定义了 AUTOEXTEND_SIZE
选项,则它将按 AUTOEXTEND_SIZE
设置和上述逻辑确定的扩展大小中的较大者进行扩展。有关 AUTOEXTEND_SIZE
选项的信息,请参见 第 17.6.3.9 节 “表空间 AUTOEXTEND_SIZE 配置”。
由于撤消日志在长时间运行的事务期间可能会变得很大,因此创建额外的撤消表空间有助于防止单个撤消表空间变得过大。可以使用 CREATE UNDO TABLESPACE
语法在运行时创建其他撤消表空间。
CREATE UNDO TABLESPACE tablespace_name ADD DATAFILE 'file_name.ibu';
撤消表空间文件名必须具有 .ibu
扩展名。定义撤消表空间文件名时,不允许指定相对路径。允许使用完全限定的路径,但该路径必须为 InnoDB
所知。已知路径是由 innodb_directories
变量定义的路径。建议使用唯一的撤消表空间文件名,以避免在移动或克隆数据时出现潜在的文件名冲突。
在复制环境中,源和每个副本都必须具有自己的撤消表空间文件目录。将撤消表空间文件的创建复制到公共目录会导致文件名冲突。
启动时,系统会扫描由 innodb_directories
变量定义的目录以查找撤消表空间文件。(扫描也会遍历子目录。)由 innodb_data_home_dir
、innodb_undo_directory
和 datadir
变量定义的目录会自动附加到 innodb_directories
值,而无论 innodb_directories
变量是否已明确定义。因此,撤消表空间可以驻留在由这些变量中的任何一个定义的路径中。
如果撤消表空间文件名不包含路径,则会在 innodb_undo_directory
变量定义的目录中创建该表空间。如果未定义该变量,则会在数据目录中创建撤消表空间。
InnoDB
恢复过程要求撤消表空间文件驻留在已知目录中。必须在重做恢复之前以及打开其他数据文件之前发现并打开撤消表空间文件,以便回滚未提交的事务和数据字典更改。恢复前找不到的撤消表空间将无法使用,这可能会导致数据库不一致。如果在启动时找不到数据字典已知的撤消表空间,则会报告错误消息。已知目录要求还支持撤消表空间的可移植性。请参阅移动撤消表空间。
要在相对于数据目录的路径中创建撤消表空间,请将 innodb_undo_directory
变量设置为相对路径,并在创建撤消表空间时仅指定文件名。
要查看撤消表空间名称和路径,请查询 INFORMATION_SCHEMA.FILES
SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES
WHERE FILE_TYPE LIKE 'UNDO LOG';
MySQL 实例最多支持 127 个撤消表空间,包括在初始化 MySQL 实例时创建的两个默认撤消表空间。
可以使用 DROP UNDO TABALESPACE
语法删除撤消表空间。请参阅删除撤消表空间。
可以使用 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
可以通过查询信息架构 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 实例时创建的默认撤消表空间(innodb_undo_001
和 innodb_undo_002
)无法删除。但是,可以使用 ALTER UNDO TABLESPACE
语句将其设为非活动状态。在将默认撤消表空间设为非活动状态之前,必须有一个撤消表空间来替代它。始终需要至少两个活动的撤消表空间才能支持自动截断撤消表空间。tablespace_name
SET INACTIVE
使用 CREATE UNDO TABLESPACE
语法创建的撤消表空间可以在服务器脱机时移动到任何已知目录。已知目录是由 innodb_directories
变量定义的目录。由 innodb_data_home_dir
、innodb_undo_directory
和 datadir
定义的目录会自动附加到 innodb_directories
值,而无论 innodb_directories
变量是否已明确定义。系统会在启动时扫描这些目录及其子目录以查找撤消表空间文件。移动到这些目录中的任何一个目录的撤消表空间文件会在启动时被发现,并假定为已移动的撤消表空间。
初始化 MySQL 实例时创建的默认撤消表空间(innodb_undo_001
和 innodb_undo_002
)必须驻留在 innodb_undo_directory
变量定义的目录中。如果未定义 innodb_undo_directory
变量,则默认撤消表空间将驻留在数据目录中。如果在服务器脱机时移动了默认撤消表空间,则必须在启动服务器时将 innodb_undo_directory
变量配置为新目录。
撤消日志的 I/O 模式使撤消表空间非常适合作为 SSD 存储。
innodb_rollback_segments
变量定义分配给每个撤消表空间和全局临时表空间的 回滚段 的数量。innodb_rollback_segments
变量可以在启动时或服务器运行时进行配置。
innodb_rollback_segments
的默认设置为 128,这也是最大值。有关回滚段支持的事务数的信息,请参阅第 17.6.6 节“撤消日志”。
有两种截断撤消表空间的方法,可以单独使用或组合使用来管理撤消表空间的大小。一种方法是自动的,使用配置变量启用。另一种方法是手动的,使用 SQL 语句执行。
自动方法不需要监视撤消表空间的大小,并且一旦启用,它就会在无需手动干预的情况下执行撤消表空间的停用、截断和重新激活。如果您希望控制何时将撤消表空间脱机进行截断,则手动截断方法可能更可取。例如,您可能希望避免在工作负载高峰期截断撤消表空间。
自动截断
自动截断撤消表空间需要至少两个活动的撤消表空间,这确保了一个撤消表空间在另一个撤消表空间脱机进行截断时保持活动状态。默认情况下,在初始化 MySQL 实例时会创建两个撤消表空间。
要自动截断撤消表空间,请启用 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
变量后
超过
innodb_max_undo_log_size
设置的默认和用户定义的撤消表空间将被标记为要截断。选择要截断的撤消表空间以循环方式执行,以避免每次都截断相同的撤消表空间。驻留在选定撤消表空间中的回滚段将被设为非活动状态,以便不会将它们分配给新事务。当前正在使用回滚段的现有事务允许完成。
清除 系统通过释放不再使用的撤消日志来清空回滚段。
释放撤消表空间中的所有回滚段后,将运行截断操作,并将撤消表空间截断为其初始大小。
由于在操作完成后立即使用,因此截断操作后撤消表空间的大小可能大于初始大小。
innodb_undo_directory
变量定义默认撤消表空间文件的位置。如果未定义innodb_undo_directory
变量,则默认撤消表空间将驻留在数据目录中。可以通过查询信息架构FILES
表来确定所有撤消表空间文件(包括使用CREATE UNDO TABLESPACE
语法创建的用户定义的撤消表空间)的位置SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE LIKE 'UNDO LOG';
回滚段将被重新激活,以便可以将它们分配给新事务。
手动截断
手动截断撤消表空间需要至少三个活动的撤消表空间。始终需要两个活动的撤消表空间,以支持启用自动截断的可能性。至少三个撤消表空间可以满足此要求,同时允许手动将撤消表空间脱机。
要手动启动撤消表空间的截断,请通过发出以下语句来停用撤消表空间
ALTER UNDO TABLESPACE tablespace_name SET INACTIVE;
在将撤消表空间标记为非活动状态后,当前使用该表空间中回滚段的事务以及在这些事务完成之前启动的任何事务都允许完成。事务完成后,清除系统会释放撤消表空间中的回滚段,将撤消表空间截断为其初始大小,并将撤消表空间状态从 inactive
更改为 empty
。
当 ALTER UNDO TABLESPACE
语句停用撤消表空间时,清除线程会在下次有机会时查找该撤消表空间。找到撤消表空间并将其标记为截断后,清除线程会更频繁地返回,以便快速清空和截断撤消表空间。tablespace_name
SET INACTIVE
要检查撤消表空间的状态,请查询信息架构 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 子系统的速度
现有的长时间运行的事务
系统负载
避免潜在性能影响的最简单方法是增加撤消表空间的数量。
监视撤消表空间截断
提供了 undo
和 purge
子系统计数器,用于监视与撤消日志截断相关的后台活动。有关计数器名称和说明,请查询信息架构 INNODB_METRICS
表。
SELECT NAME, SUBSYSTEM, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%truncate%';
有关启用计数器和查询计数器数据的更多信息,请参阅第 17.15.6 节“InnoDB INFORMATION_SCHEMA 指标表”。
撤消表空间截断限制
在检查点之间,对同一个撤消表空间执行的截断操作次数限制为 64 次。此限制可以防止由于撤消表空间截断操作次数过多而导致的潜在问题,例如,如果在繁忙的系统上将 innodb_max_undo_log_size
设置得太低,就可能会发生这种情况。如果超过了限制,仍然可以停用撤消表空间,但在下一个检查点之前不会对其进行截断。在 MySQL 8.4 中,限制为 50000。
撤消表空间截断恢复
撤消表空间截断操作会在服务器日志目录中创建一个临时文件 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 |
+----------------------------------+-------+
有关状态变量的说明,请参阅第 7.1.10 节“服务器状态变量”。