MySQL 5.7:自动回收UNDO表空间

2023年 12月 11日 45.6k 0

  • undo log segment(undo segment)Undo Logs 合集。undo segment 可以被重复使用,但是一次只能由一个事务占用。
  • rollback segment也就是 Undo Logs 的物理存储区域。
  • undo tablespacerollback segment 被从系统表空间里分离出来后的实际磁盘文件表现形式。

所以基本关系如下:undo log -> undo log segment-> rollback segment->undo tablespace

一、MySQL 5.5 时代的 undo 日志

InnoDB 存储引擎中,undo 日志一直都是事务多版本控制中的核心组件,它具有以下的核心功能:

  • 事务的回退:事务在处理过程中遇到异常的时候可以 rollback 所做的全部修改。
  • 事务的恢复:数据库实例崩溃时,将磁盘的不正确数据恢复到交易前。
  • 读一致性:被查询的记录有事务占用,转向回滚段找事务开始前的数据镜像。

没有被活跃事务用到的 undo 日志就可以被 purge 掉了,但 undo 在事务执行过程中,进行的空间分配如何回收,就变成了一个问题。亲历因为一个大事务,导致 ibdata file 到 800G 大小。

在 MySQL5.5 以及之前,大家会发现随着数据库上线时间越来越长,ibdata1 文件(即 InnoDB 的共享表空间,或者系统表空间)会越来越大,这会造成 2 个比较明显的问题:

  • 磁盘剩余空间越来越小,到后期往往要加磁盘;
  • 物理备份时间越来越长,备份文件也越来越大。

这是怎么回事呢?

原因除了数据量自然增长之外,在 MySQL 5.5 以及之前,InnoDB 的 undo 日志也是存放在 ibdata1 里面的。一旦出现大事务,这个大事务所使用的 undo 日志占用的空间就会一直在 ibdata1 里面存在,即使这个事务已经关闭。虽然这部分空间可以重用, 但文件大小不能更改。

那么问题来了,有办法把上面说的空闲的 undo 日志占用的空间从 ibdata1 里面清理掉吗?答案是没有直接的办法,只能全库导出 sql 文件,然后重新初始化 MySQL 实例,再全库导入。

关于回滚段的,只有这个主要的参数,用来设置多少个 rollback segment。

1

2

3

4

5

6

mysql> show global variables like '%rollback_segment%';  

+----------------------------+-------+  

| Variable_name              | Value |  

+----------------------------+-------+  

| innodb_rollback_segments   | 128   |  

+----------------------------+-------+

二、MySQL 5.6 时代的 undo 日志

在 MySQL 5.6 中开始支持把 undo 日志分离到独立的表空间,也称之为 undo 表空间,并放到单独的文件目录下;这给我们部署不同 IO 类型的文件位置带来便利,对于并发写入型负载,我们可以把 undo 表空间部署到单独的高速存储设备上。

undo 表空间包含 undo 日志,这是一些记录的集合,包含 undo 事务对聚类索引记录的最新更改的信息。

undo 日志默认存储在系统表空间中,但也可以存储在一个或多个 undo 表空间中。增加了如下几个参数来管理 undo 日志。

1

2

3

4

5

6

7

8

mysql> show global variables like '%undo%';

+-------------------------+-------+  

| Variable_name           | Value |  

+-------------------------+-------+  

| innodb_undo_directory   | .     |  

| innodb_undo_logs        | 128   |  

| innodb_undo_tablespaces | 0     |  

+-------------------------+-------+

innodb_undo_directory

当开启独立 undo 表空间时,指定 undo 文件存放的目录,就是用于设置 rollback segment(回滚段)文件所在的路径。这意味着 rollback segment 可以存放在共享表空间以外的位置,即可以设置为独立表空间。该参数的默认值为 “.”,表示当前 InnoDB 存储引擎的数据目录。如果我们想转移 undo 文件的位置,只需要修改下该配置,并将 undo 文件拷贝过去就可以了。

innodb_undo_logs

用来设置 rollback segment(回滚段)的个数,默认为 128。在 InnoDB 1.2 版本中,该参数用来替换之前版本的参数 innodb_rollback_segments。该变量可以动态调整,但是物理上的回滚段不会减少,只是会控制用到的回滚段的个数。

innodb_undo_tablespaces

用于设定创建的 undo 表空间的个数,也就是用来构成 rollback segment 文件的数量,这样 rollback segment 可以较为平均地分布在多个文件中。该选项只能在初始化 MySQL 实例时配置,之后无法更改,默认值为 0,表示不独立设置 undo 的表空间,默认记录到 ibdata 中;否则,则在 undo 目录下创建这么多个 undo 文件,例如假定设置该值为 16,那么就会创建命名为 undo001~undo016 的 undo 表空间文件,每个文件的默认大小为 10M。并且会在路径 innodb_undo_directory 看到 undo 为前缀的文件。

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论