13 | 为什么表数据删掉一半,表文件大小不变?

13 | 为什么表数据删掉一半,表文件大小不变?

参数 innodb_file_per_table

表数据既可以存在共享表空间里,也可以是单独的文件。这个行为是由参数 innodb_file_per_table 控制的:

  • ON 表示的是,每个 InnoDB 表数据存储在一个以 .ibd 为后缀的文件中
  • OFF 表示的是,表的数据放在系统共享表空间,也就是跟数据字典放在一起

默认值为 ON。

数据删除流程

InnoDB 里的数据都是用 B+ 树的结构组织的。

当删除数据记录时,InnoDB 引擎会把对应的数据记录标记为删除,之后这个被标记为删除的位置,会被复用。

如果删除了一个数据页上的所有记录,整个数据页就会被复用。

记录的复用:只限于符合范围条件的数据。

数据页的复用:可复用到任何位置。

delete 命令其实只是把记录的位置,或者数据页标记为了“可复用”,但磁盘文件的大小是不会变的。这些可以复用的没被使用的空间,也称为 “空洞”。

空洞的原因:

  • 删除表记录,被删除的记录只是被标记删除,索引值所在的空间能被复用,但是没有真正的删除。
  • 新增表记录,如果索引的值是随机分散的,那么会造成数据页的分裂,也会造成空洞
  • 更新索引上的值,实际上是把旧值标记为删除,然后新增一个新值,旧值虽然能被复用,但是还是造成了空洞

只有把这些空洞去掉,就能达到收缩表空间的目的。而重建表,就可以达到这样的目的。

重建表

使用 alter table A engine=InnoDB 命令来重建表。

在重建表的过程中,允许对表 A 做增删改操作。即 Online DDL。

Online DDL ,重建表的流程:

1、建立一个临时文件,扫描表 A 主键的所有数据页;

2、用数据页中表 A 的记录生成 B+ 树,存储到临时文件中;

3、生成临时文件的过程中,将所有对 A 的操作记录在一个日志文件(row log)中,对应的是图中 state2 的状态;

4、临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表 A 相同的数据文件,对应的就是图中 state3 的状态;

5、用临时文件替换表 A 的数据文件。

image-20230701152024763

DDL 之前是要拿 MDL 写锁的,这样还能叫 Online DDL 吗?

alter 语句在启动的时候需要获取 MDL 写锁,但是这个写锁在真正拷贝数据之前就退化成读锁了。

为什么要退化呢?为了实现 Online,MDL 读锁不会阻塞增删改操作。

那为什么不干脆直接解锁呢?为了保护自己,禁止其他线程对这个表同时做 DDL。

Online 和 inplace

Online的意义是代表在操作表时不会阻塞其增删改的过程

inplace的意义是修改表时直接操作其原表,操作在引擎层内部完成.

与之相对的是copy方式,操作方式是新建一个修改后的表,再将原表的内容一条一条的拷贝到新表上,其效率更慢

  • DDL 过程如果是 Online 的,就一定是 inplace 的;
  • 反过来未必,也就是说 inplace 的 DDL,有可能不是 Online 的。截止到 MySQL 8.0,添加全文索引(FULLTEXT index)和空间索引 (SPATIAL index) 就属于这种情况。

optimize table、analyze table 和 alter table 这三种方式重建表的区别

  • alter table 重建表,减少页空洞
  • analyze table 重新统计索引信息
  • optimize table 重建+重新统计
posted @ 2023-07-01 15:35  LionelYee  阅读(38)  评论(0编辑  收藏  举报