数一数本机真实有几个undo tablespace,用DDL动态新建再删除一个,再用500次真实小更新验证它的磁盘占用到底会不会随便涨。
代码SELECT SPACE, NAME, STATE, FILE_SIZE FROM information_schema.INNODB_TABLESPACES WHERE NAME LIKE '%undo%';
SPACE NAME STATE FILE_SIZE 4294967279 innodb_undo_001 active 33554432 (32MB) 4294967278 innodb_undo_002 active 33554432 (32MB)
$ ls -la /opt/homebrew/var/mysql/undo_* -rw-r----- 1 w admin 33554432 undo_001 -rw-r----- 1 w admin 33554432 undo_002
这两个undo tablespace是InnoDB初始化数据目录时真实自动创建的,从MySQL 8.0开始不再需要靠innodb_undo_tablespaces参数手动指定数量——这个变量在真实的MySQL 26.7.0里查询会直接报"Unknown system variable",取而代之的是CREATE UNDO TABLESPACE/DROP UNDO TABLESPACE这套DDL语法,undo tablespace的数量真实变成了可以运行时动态增减的对象。
CREATE UNDO TABLESPACE undo_003 ADD DATAFILE 'undo_003.ibu'; → 真实新增一行:SPACE=...277, NAME=undo_003, STATE=active, FILE_SIZE=16777216(16MB) → 磁盘上真实多了一个文件:undo_003.ibu,16MB ALTER UNDO TABLESPACE undo_003 SET INACTIVE; → STATE真实变成 empty DROP UNDO TABLESPACE undo_003; → 磁盘上的undo_003.ibu文件真实被删除
新建的这个undo tablespace初始大小是16MB,比默认的两个(32MB)小——这是两种不同的创建路径:默认的两个是数据目录初始化时按老的固定尺寸创建的,运行时用DDL新建的走的是另一套初始化逻辑。要删除一个undo tablespace,真实必须先用SET INACTIVE把它标记成不再接受新事务,等它内部真实的历史数据被purge线程清空之后,才能真实DROP掉——不能对一个还在被使用的undo tablespace直接删除。
500次真实独立的UPDATE(各自单行、各自提交)之前: innodb_undo_001: 33554432 innodb_undo_002: 33554432 500次之后: innodb_undo_001: 33554432 innodb_undo_002: 33554432 ← 完全没变
每一步都是本文上面用真实DDL和information_schema跑出来的原始结果。
information_schema.INNODB_TABLESPACES、真实磁盘文件核对CREATE/ALTER/DROP UNDO TABLESPACE:MySQL 8.0起真实支持的动态DDL