MySQL8.0 - 新特性 - 通过SQL管理UNDO TABLESPACE

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS SQL Server,基础系列 2核4GB
简介: 前言 InnoDB的undo log从5.6版本开始可以存储到单独的tablespace文件中,在5.7版本支持了在线undo文件truncate,解决了长期以来的undo膨胀问题。而到了8.0版本,对Undo tablespace做了进一步的优化:在新版本中,我们可以拥有更多的回滚段(每个Undo tablespace可以有128个回滚段,而在之前的版本中所有tablespace的回滚段不允许超过128个),减少了由于事务公用回滚段产生的锁冲突;可以在线动态的增删undo tablespace,使得undo的管理更加灵活。

前言

InnoDB的undo log从5.6版本开始可以存储到单独的tablespace文件中,在5.7版本支持了在线undo文件truncate,解决了长期以来的undo膨胀问题。而到了8.0版本,对Undo tablespace做了进一步的优化:在新版本中,我们可以拥有更多的回滚段(每个Undo tablespace可以有128个回滚段,而在之前的版本中所有tablespace的回滚段不允许超过128个),减少了由于事务公用回滚段产生的锁冲突;可以在线动态的增删undo tablespace,使得undo的管理更加灵活。

在最近release的8.0.14版本中,开始支持SQL接口来创建,修改和删除 (undo space的管理不记录binlog)。可以预见未来将逐步废弃根据配置innodb_undo_tablespaces来创建undo tablespace, 通过SQL接口来创建undo tablespace将是唯一的接口。实际上在最新版本中已经将参数innodb_undo_tablespaces标记为deprecated状态,用户应尽量避免依赖该参数。

SQL语句

implict undo space

在安装实例时,会默认创建两个undo tablespace:

mysql> SELECT * FROM  INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE ROW_FORMAT = 'Undo'\G
*************************** 1. row ***************************
         SPACE: 4294967279
          NAME: innodb_undo_001
          FLAG: 0
    ROW_FORMAT: Undo
     PAGE_SIZE: 16384
 ZIP_PAGE_SIZE: 0
    SPACE_TYPE: Undo
 FS_BLOCK_SIZE: 0
     FILE_SIZE: 0
ALLOCATED_SIZE: 0
SERVER_VERSION: 8.0.15
 SPACE_VERSION: 1
    ENCRYPTION: N
         STATE: active
*************************** 2. row ***************************
         SPACE: 4294967278
          NAME: innodb_undo_002
          FLAG: 0
    ROW_FORMAT: Undo
     PAGE_SIZE: 16384
 ZIP_PAGE_SIZE: 0
    SPACE_TYPE: Undo
 FS_BLOCK_SIZE: 0
     FILE_SIZE: 0
ALLOCATED_SIZE: 0
SERVER_VERSION: 8.0.15
 SPACE_VERSION: 1
    ENCRYPTION: N
         STATE: active
2 rows in set (0.00 sec)

mysql> SHOW GLOBAL STATUS LIKE '%UNDO_TABLESPACE%';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| Innodb_undo_tablespaces_total    | 2     |
| Innodb_undo_tablespaces_implicit | 2     |
| Innodb_undo_tablespaces_explicit | 0     |
| Innodb_undo_tablespaces_active   | 2     |
+----------------------------------+-------+
4 rows in set (0.00 sec)

创建新的undo space

你可以通过如下语句来创建独立的undo tablespace, 文件后缀必须以ibu结尾。新创建的tablespace为active状态

mysql> CREATE UNDO TABLESPACE myundo ADD DATAFILE 'myundo.ibd';
ERROR 3121 (HY000): The ADD DATAFILE filepath must end with '.ibu'.

mysql> CREATE UNDO TABLESPACE myundo ADD DATAFILE 'myundo.ibu';
Query OK, 0 rows affected (0.26 sec)

mysql> SELECT * FROM  INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE ROW_FORMAT = 'Undo' and NAME = 'myundo'\G
*************************** 1. row ***************************
         SPACE: 4294967277
          NAME: myundo
          FLAG: 0
    ROW_FORMAT: Undo
     PAGE_SIZE: 16384
 ZIP_PAGE_SIZE: 0
    SPACE_TYPE: Undo
 FS_BLOCK_SIZE: 0
     FILE_SIZE: 0
ALLOCATED_SIZE: 0
SERVER_VERSION: 8.0.15
 SPACE_VERSION: 1
    ENCRYPTION: N
         STATE: active                       --> 此时状态为active
1 row in set (0.01 sec)

在创建undo space时,你可以使用绝对路径,也可以放在实例配置的undo目录下,但要注意一点:在崩溃恢复前undo space必须要能够被发现并打开,但这时候Innodb data dictionary还是处于不可用的状态,我们无法从其中获取准确的文件位置,只有--datadir, --innodb-home-directory, --innodb-undo-directory 和 --innodb-directories会被扫描掉,如果你放在其他地方,就可能造成找不到该tablespace, 导致实例数据不一致。

相关代码:

  • Server层接口类:Sql_cmd_create_undo_tablespace
  • 为undo tablespace预留的space id (但最多依然是127个undo tablespace, 每个space number会给一个范围内的space id, 默认512个id):

    • s_min_undo_space_id = 0xFFFFFFF0UL - 127 * 512
    • s_max_undo_space_id = 0xFFFFFFF0UL - 1
  • InnoDB入口函数: innodb_create_undo_tablespace

    • 获取下一个可用的space id: undo::get_next_available_space_num(), 先拿到空闲的space number,再分配一个可用的space id
    • srv_undo_tablespace_create: 创建undo space, 初始化回滚段并加入到全局事务系统中
    • 提交变更,持久化tablespace信息后,将其设置为active状态,此后事务可以从其中分配到回滚段

设置inactive

如果你不想使用某个Undo tablespace,可以将其设置为inactive状态, 但需要保证至少有连个active的undo tablespace, 这个限制的原因是:当一个undo tablespace正在被truncate时,至少有一个是可用的。

当被设置为Inactive状态之后,事务就不会从其中分配回滚段。

mysql> ALTER UNDO TABLESPACE myundo SET INACTIVE;
Query OK, 0 rows affected (0.01 sec)

相关代码:

  • server层接口类:Sql_cmd_alter_undo_tablespace
  • 在崩溃恢复data dicitonary提供服务后,需要将undo space状态更新到内存(apply_dd_undo_state()
  • innodb_alter_undo_tablespace--> innodb_alter_undo_tablespace_active

    • 设置Undo space 为active状态,并修改dd元数据
  • innodb_alter_undo_tablespace --> innodb_alter_undo_tablespace_inactive

    • 当undo space状态为empty时,直接返回
    • 当undo space状态为active时,需要确保至少两个active的undo space才允许操作,否则返回错误
    • 设置dd state为inactive,并修改回滚段状态
    • 设置truncate frequency为1并唤醒purge线程, 这样purge线程会更频繁的去做purge操作,加快undo space的回收

删除undo space

在删除一个undo tablespace之前,首先要把undo tablespace设置为inactive状态

mysql> DROP UNDO TABLESPACE myundo;
ERROR 1529 (HY000): Failed to drop UNDO TABLESPACE myundo

mysql> ALTER UNDO TABLESPACE myundo SET INACTIVE;
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT * FROM  INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE ROW_FORMAT = 'Undo' and Name = 'myundo'\G
*************************** 1. row ***************************
         SPACE: 4294967150
          NAME: myundo
          FLAG: 0
    ROW_FORMAT: Undo
     PAGE_SIZE: 16384
 ZIP_PAGE_SIZE: 0
    SPACE_TYPE: Undo
 FS_BLOCK_SIZE: 0
     FILE_SIZE: 0
ALLOCATED_SIZE: 0
SERVER_VERSION: 8.0.15
 SPACE_VERSION: 1
    ENCRYPTION: N
         STATE: empty     --> 此时undo space内没有任何Undo log, 已经是empty可删除状态
1 row in set (0.00 sec)

mysql> DROP UNDO TABLESPACE myundo;
Query OK, 0 rows affected (0.02 sec)

即使状态为inactive的,但要保证如下几点才能被删除:

  • 没有任何事务需要看到其中的老版本数据,也就是说所有在该事务之前开启的read view必须全部关闭
  • 所有使用该undo tablespace的事务必须全部提交或回滚掉
  • purge线程需要将其中的Undo log全部清理掉

如果undo tablespace非空,在drop时,会返回错误码HA_ERR_TABLESPACE_IS_NOT_EMPTY. 所以在设置为inactive到真正可以删除可能存在时间差,我们可以通过监控INFORMATION_SCHEMA.INNODB_TABLESPACES中的undo space状态是否为empty来判定是否可以删除。 Note:系统创建的Undo space不允许被删除

相关代码:

  • Server层接口类:Sql_cmd_drop_undo_tablespace
  • InnoDB 入口函数: innodb_drop_undo_tablespace

    • 当undo space状态不为emtpy时或者是系统创建的Undo space时,不允许删除
    • invalidate buffer pool中该space的page
    • 从内存中删除,记录ddl log
    • 事务提交后,执行post ddl (Log_DDL::replay_delete_space_log)

      • 真正物理删除文件
      • 标记对应的space num为未使用状态

undo truncation

当参数innodb_undo_log_truncate打开时,所有隐式和显式创建的Undo tablespace都会在满足一定条件时被purge线程truncate掉. 当参数关闭时,则只有将Undo tablespace设置为Inactive状态时才会去truncate tablespace。 因此如果你想自己控制undo truncation, 可以关闭参数,在监控undo tablespace的大小,通过SET INACTIVE触发truncation, 再通过SET ACTIVE激活undo space。

相关代码:

  • 由purge线程发起,入口函数:trx_purge_truncate_marked_undo()
  • 需要获取MDL锁,来保护space不被alter/drop
  • 通过flush_observer flush当前space的page
  • trx_purge_truncate_marked_undo_low

    • trx_undo_truncate_tablespace:

      • 为当前space分配一个新的space id: undo::use_next_space_id(space_num)
      • fil_replace_tablespace: 删除当前undo space,重建文件并设置为新的space id
      • 重新初始化回滚段和内存信息
      • 根据新的space id,将所有变更刷到磁盘
      • 如果是用户创建的undo space,将状态设置为empty,否则设置为active状态
      • 更新DD

为何需要新的space id ? 这是因为在删除重建文件的过程中我们没有做checkpoint,这时候如果crash掉,有些redo log可能需要修改一些已经不存在的page,导致崩溃恢复时候(ref: bug93170)

Reference

1. WL#9508: InnoDB: Support CREATE/ALTER/DROP UNDO TABLESPACE
2. WL#9507: InnoDB: Make the number of undo tablespaces and rollback segments dynamic
3. 主要代码
4. 官方文档
5. MySQL8.0 · 引擎特性 · 关于undo表空间的一些新变化

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
17天前
|
SQL 关系型数据库 MySQL
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
MySQL事务日志-Undo Log工作原理分析
|
27天前
|
SQL 安全 关系型数据库
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
事务是MySQL中一组不可分割的操作集合,确保所有操作要么全部成功,要么全部失败。本文利用SQL演示并总结了事务操作、事务四大特性、并发事务问题、事务隔离级别。
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
|
27天前
|
SQL 存储 关系型数据库
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
本文详细介绍了MySQL中的SQL语法,包括数据定义(DDL)、数据操作(DML)、数据查询(DQL)和数据控制(DCL)四个主要部分。内容涵盖了创建、修改和删除数据库、表以及表字段的操作,以及通过图形化工具DataGrip进行数据库管理和查询。此外,还讲解了数据的增、删、改、查操作,以及查询语句的条件、聚合函数、分组、排序和分页等知识点。
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
|
29天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
70 3
|
1月前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
1月前
|
SQL 关系型数据库 MySQL
MySQL 高级(进阶) SQL 语句
MySQL 提供了丰富的高级 SQL 语句功能,能够处理复杂的数据查询和管理需求。通过掌握窗口函数、子查询、联合查询、复杂连接操作和事务处理等高级技术,能够大幅提升数据库操作的效率和灵活性。在实际应用中,合理使用这些高级功能,可以更高效地管理和查询数据,满足多样化的业务需求。
193 3
|
1月前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
1月前
|
SQL 存储 关系型数据库
MySQL进阶突击系列(01)一条简单SQL搞懂MySQL架构原理 | 含实用命令参数集
本文从MySQL的架构原理出发,详细介绍其SQL查询的全过程,涵盖客户端发起SQL查询、服务端SQL接口、解析器、优化器、存储引擎及日志数据等内容。同时提供了MySQL常用的管理命令参数集,帮助读者深入了解MySQL的技术细节和优化方法。
|
1月前
|
SQL Oracle 关系型数据库
SQL(MySQL)
SQL语言是指结构化查询语言,是一门ANSI的标准计算机语言,用来访问和操作数据库。 数据库包括SQL server,MySQL和Oracle。(语法大致相同) 创建数据库指令:CRATE DATABASE websecurity; 查看数据库:show datebase; 切换数据库:USE websecurity; 删除数据库:DROP DATABASE websecurity;
|
2月前
|
关系型数据库 MySQL
mysql事务特性
原子性:一个事务内的操作统一成功或失败 一致性:事务前后的数据总量不变 隔离性:事务与事务之间相互不影响 持久性:事务一旦提交发生的改变不可逆

相关产品

  • 云数据库 RDS MySQL 版