撤销表空间包含撤销日志,撤销日志是包含记录的集合,这些记录包含有关如何撤销事务对聚集索引记录的最新更改的信息。
本节中的以下主题介绍了撤销表空间。
在 MySQL 实例初始化时创建两个默认撤销表空间。默认撤销表空间是在初始化时创建的,以提供在接受 SQL 语句之前必须存在的回滚段的位置。至少需要两个撤销表空间才能支持撤销表空间的自动截断。请参阅 截断撤销表空间.
默认撤销表空间是在由 innodb_undo_directory
变量定义的位置创建的。如果 innodb_undo_directory
变量未定义,则默认撤销表空间将在数据目录中创建。默认撤销表空间数据文件名为 undo_001
和 undo_002
。在数据字典中定义的相应撤销表空间名为 innodb_undo_001
和 innodb_undo_002
。
可以使用 SQL 语句在运行时创建其他撤销表空间。请参阅 添加撤销表空间.
初始撤销表空间大小通常为 16MiB。当通过截断操作创建新的撤销表空间时,初始大小可能会有所不同。在这种情况下,如果文件扩展大小大于 16MB,并且之前的文件扩展发生在最后 1 秒内,则新撤销表空间将在由 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 9.0 中,该限制为 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 节“服务器状态变量”。