作者:Kevin Lewis 译:徐轶韬
UNDO表空间可以在MySQL 8.0中隐式或显式截断。两种方法使用相同的机制。当UNDO表空间截断完成时,可能导致非常繁忙的系统上的定期停顿。此问题已在MySQL 8.0.21中修复。
首先,让我们了解可用于防止UNDO表空间过大的两种方法。
隐式截断
默认情况下,隐式方法在MySQL 8.0中为ON。设置innodb_undo_log_truncate(默认= ON)和innodb_max_undo_log_size(默认= 1GB)。使用这些设置,如果UNDO表空间增长到大于1 GB,则InnoDB中的后台清除线程会将其脱机。当与UNDO表空间中的UNDO日志关联的所有事务都已完成,并且不再需要该空间中的所有UNDO日志来保护数据完整性时,就可以将表空间截断了。
之后删除表空间,并创建一个新的UNDO表空间来替换它。一旦新的表空间准备就绪,它将再次变为活动状态。
显式截断
当用户认为表空间在磁盘上变得太大时,就可以在UNDO表空间上显式激活截断过程:
ALTER UNDO TABLESPACE tablespace_name SET INACTIVE;
然后,您可以通过下面的语句监视进程是否仍在等待不必要的UNDO日志,或者表空间是否已完全截断:
SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME = ‘tablespace_name’;
详细内容请参阅在线手册https://dev.mysql.com/doc/refman/8.0/en/innodb-undo-table和一个博客文章https://mysqlserverteam.com/online-truncate-of-innodb-undo-tablespaces/。
8.0.21的改进
在一个非常繁忙的系统上,我们注意到实际的截断会导致性能下降,因为它会将UNDO表空间中的所有页面从缓冲池中清除出来。因此,在MySQL 8.0.21中,在删除了关联的撤消数据文件之后,InnoDB现在将那些页面留在缓冲池中。InnoDB知道这些页面用于已删除的表空间ID。由于页面变得很少使用,它们将被动释放。之后,在下一个完整的检查点,释放剩余的缓冲区以再次使用。内部缓冲池管理功能能够使UNDO表空间截断几乎是瞬时的。
改进的另一部分是新的UNDO表空间进行了完整的重做日志,这意味着作为截断操作的一部分,UNDO表空间的最初129页不必刷新到磁盘。
这些改进缓解了QA小组在UNDO截断处于活动状态时,在极为繁忙的服务器上的遇到的周期性停顿。
InnoDB对单个UNDO表空间使用512个唯一表空间ID范围。每次UNDO表空间被截断时,它都会获得一个新的ID,该ID以循环方式分配。如果出现混乱,例如在繁忙的系统上innodb_max_undo_log_size太小,或者在循环中显式地截断相同的UNDO表空间时,我们发现在两个检查点之间,UNDO表空间可能会被截断512次以上。如果发生这种情况,那么同一UNDO表空间的512个不同版本的缓冲池中可能有页面,或者重做日志中可能有更改。在压力测试中,这导致InnoDB中的判断提示失败。我们的QA小组可以再现这一情景。因此,为避免这种情况,InnoDB不再允许在两个检查点之间发生超过64个相同的撤消表空间的截断。
这种小小的性能改进是InnoDB不断提高的另一种方式。