撤销表空间包含撤销日志,撤销日志是包含事务对聚簇索引记录所做的最新更改信息的记录集合。
撤销表空间在本节中描述以下主题:
在 MySQL 实例初始化时创建两个默认撤销表空间。默认撤销表空间是在初始化时创建的,以便提供回滚段的位置,以便在 SQL 语句可以被接受之前。至少需要两个撤销表空间来支持自动截断撤销表空间。请参阅 截断撤销表空间。
默认撤销表空间是在 innodb_undo_directory
变量定义的位置创建的。如果 innodb_undo_directory
变量未定义,默认撤销表空间将在数据目录中创建。默认撤销表空间数据文件名为 undo_001
和 undo_002
。对应的撤销表空间名称在数据字典中定义为 innodb_undo_001
和 innodb_undo_002
。
可以在运行时使用 SQL 语句创建额外的撤销表空间。请参阅 添加撤销表空间。
撤销表空间的初始大小通常为 16MiB。初始大小可能在 truncate 操作中创建新的撤销表空间时有所不同。在这种情况下,如果文件扩展大小大于 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
恢复过程要求撤销表空间文件驻留在已知目录中。撤销表空间文件必须在redo恢复之前被发现和打开,以便回滚未提交的事务和数据字典更改。如果在恢复之前未找到撤销表空间,可能会导致数据库不一致。在启动时,如果数据字典中已知的撤销表空间未被找到,将报告错误信息。已知目录要求也支持撤销表空间的可移植性。见移动撤销表空间。
要在数据目录的相对路径中创建撤销表空间,请将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;
在undo表空间被标记为非活动状态后,当前使用回滚段的交易将被允许完成,同时也允许在这些交易完成之前启动的交易。完成交易后,清除系统将释放undo表空间中的回滚段,并将undo表空间截断到其初始大小。(同样的过程也适用于截断undo表空间。参见截断Undo Tablespaces。)一旦undo表空间为空,它就可以被删除。
DROP UNDO TABLESPACE tablespace_name;
或者,undo表空间可以保持为空状态,并在需要时重新激活,通过发出ALTER UNDO TABLESPACE
语句。tablespace_name
SET ACTIVE
可以通过查询Information Schema INNODB_TABLESPACES
表来监控undo表空间的状态。
SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
WHERE NAME LIKE 'tablespace_name';
一个inactive
状态表明undo表空间中的回滚段不再被新交易使用。一个empty
状态表明undo表空间为空并准备好被删除,或者准备好重新激活使用ALTER UNDO TABLESPACE
语句。尝试删除不为空的undo表空间将返回错误。tablespace_name
SET ACTIVE
默认的undo表空间(innodb_undo_001
和innodb_undo_002
)在MySQL实例初始化时创建不能被删除。它们可以,但是,使用ALTER UNDO TABLESPACE
语句被标记为非活动状态。在默认的undo表空间被标记为非活动状态之前,必须有一个undo表空间来取代它。至少需要两个活动的undo表空间来支持自动截断undo表空间。tablespace_name
SET INACTIVE
使用CREATE UNDO TABLESPACE
语法创建的undo表空间可以在服务器离线时移动到任何已知目录。已知目录是由innodb_directories
变量定义的。由innodb_data_home_dir
、innodb_undo_directory
和datadir
定义的目录将自动追加到innodb_directories
值中,无论innodb_directories
变量是否被明确定义。这些目录及其子目录将在启动时被扫描以查找undo表空间文件。移动到这些目录中的undo表空间文件将在启动时被发现,并被认为是被移动的undo表空间。
默认的undo表空间(innodb_undo_001
和innodb_undo_002
)在MySQL实例初始化时创建必须驻留在innodb_undo_directory
变量定义的目录中。如果innodb_undo_directory
变量未定义,默认的undo表空间将驻留在数据目录中。如果默认的undo表空间在服务器离线时被移动,服务器必须使用innodb_undo_directory
变量配置到新目录时启动。
Undo日志的I/O模式使undo表空间成为SSD
存储的良好候选。
变量 innodb_rollback_segments
定义了每个撤销表空间和全局临时表空间分配的撤销段数。变量 innodb_rollback_segments
可以在启动时或服务器运行时配置。
变量 innodb_rollback_segments
的默认设置为 128,这也是最大值。有关撤销段支持的交易数量的信息,请参阅 第 17.6.6 节,“撤销日志”。
有两种截断撤销表空间的方法,可以单独使用或组合使用以管理撤销表空间大小。一个方法是自动化的,使用配置变量启用。另一个方法是手动的,使用 SQL 语句执行。
自动化方法不需要监控撤销表空间大小,一旦启用,就会在不需要手动干预的情况下执行撤销表空间的停用、截断和重新激活。手动截断方法可能更适合您想要控制何时截断撤销表空间的情况。例如,您可能想避免在高峰工作负载期间截断撤销表空间。
Automated Truncation
自动截断撤销表空间需要至少两个活动撤销表空间,这确保了在一个撤销表空间被截断时,另一个撤销表空间保持活动。默认情况下,在 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
设置的默认和用户定义的撤销表空间将被标记为截断。选择撤销表空间以截断是循环进行的,以避免每次截断同一个撤销表空间。 -
驻留在所选撤销表空间中的回滚段将被停用,以便不再分配给新事务。当前使用回滚段的现有事务将被允许完成。
-
purge 系统通过释放不再使用的撤销日志来清空回滚段。
-
在所有回滚段被释放后,截断操作将运行并将撤销表空间截断到其初始大小。
截断操作完成后,撤销表空间的大小可能大于初始大小,因为立即使用了该操作。
变量
innodb_undo_directory
定义了默认撤销表空间文件的位置。如果变量innodb_undo_directory
未定义,默认撤销表空间将驻留在数据目录中。所有撤销表空间文件的位置,包括使用CREATE UNDO TABLESPACE
语法创建的用户定义撤销表空间,可以通过查询 Information SchemaFILES
表来确定:SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE LIKE 'UNDO LOG';
-
回滚段将被重新激活,以便分配给新事务。
Manual Truncation
手动截断撤销表空间需要至少三个活动撤销表空间。两个活动撤销表空间在任何时候都需要支持自动截断的可能性。三个撤销表空间的最小数量满足了这个要求,同时允许撤销表空间被手动截断。
要手动启动撤销表空间的截断,请停用撤销表空间,发出以下语句:
ALTER UNDO TABLESPACE tablespace_name SET INACTIVE;
在undo表空间被标记为非活动状态后,当前使用回滚段的事务被允许完成,同时启动在这些事务完成之前的任何事务。完成事务后,清除系统释放undo表空间中的回滚段,undo表空间被截断到其初始大小,并且undo表空间状态从inactive
更改为empty
。
当ALTER UNDO TABLESPACE
语句停用undo表空间时,清除线程将在下一个机会中查找该undo表空间。找到undo表空间并标记为截断后,清除线程将以增加的频率返回,以快速清空和截断undo表空间。tablespace_name
SET INACTIVE
要检查undo表空间的状态,请查询信息模式INNODB_TABLESPACES
表。
SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
WHERE NAME LIKE 'tablespace_name';
一旦undo表空间处于empty
状态,就可以通过发出以下语句重新激活它:
ALTER UNDO TABLESPACE tablespace_name SET ACTIVE;
undo表空间在empty
状态下也可以被删除。请参阅删除Undo Tablespaces。
Expediting Automated Truncation of Undo Tablespaces
清除线程负责清空和截断undo表空间。默认情况下,清除线程每128次调用purge时查找undo表空间以截断。控制清除线程查找undo表空间以截断的频率的变量是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次调用purge时查找undo表空间,请将innodb_purge_rseg_truncate_frequency
设置为32。
mysql> SET GLOBAL innodb_purge_rseg_truncate_frequency=32;
Performance Impact of Truncating Undo Tablespace Files
当undo表空间被截断时,undo表空间中的回滚段被停用。其他undo表空间中的活动回滚段承担整个系统负载,这可能会导致轻微的性能下降。性能受到影响的程度取决于多个因素:
-
undo表空间的数量
-
undo日志的数量
-
undo表空间的大小
-
I/O子系统的速度
-
现有的长时间运行的事务
-
系统负载
避免潜在性能影响的最简单方法是增加undo表空间的数量。
Monitoring Undo Tablespace Truncation
undo
和purge
子系统计数器提供了监视背景活动相关的undo日志截断的功能。对于计数器名称和描述,请查询信息模式INNODB_METRICS
表。
SELECT NAME, SUBSYSTEM, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%truncate%';
有关启用计数器和查询计数器数据的信息,请参阅第17.15.6节,“InnoDB INFORMATION_SCHEMA Metrics Table”。
Undo Tablespace Truncation Limit
在检查点之间对同一个undo表空间的截断操作的次数限制为64。该限制防止了可能由于innodb_max_undo_log_size
设置太低而导致的undo表空间截断操作过多的问题,例如。在MySQL 8.3中,该限制为50000。
Undo Tablespace Truncation Recovery
undo表空间截断操作创建了一个临时undo_
文件在服务器日志目录中。该日志目录由space_number
_trunc.loginnodb_log_group_home_dir
定义。如果在截断操作期间发生系统故障,该临时日志文件允许启动过程识别undo表空间并继续操作。
以下状态变量允许跟踪undo表空间的总数、隐式(InnoDB创建的)undo表空间、显式(用户创建的)undo表空间和活动undo表空间的数量:
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 节,“服务器状态变量”。