一个InnoDB表包含两部分:表结构定义和数据。在MySQL 8.0版本前,表结构存在以.frm为后缀的文件里。之后的版本允许把表结构定义放在系统数据表中。由于表结构定义占用空间很小,所以主要讨论表数据。
接下来,先说明为什么简单删除表数据达不到表空间回收的效果,再介绍正确回收空间的方法。
参数innodb_file_per_table
表数据既可以存在共享表空间里,也可以是单独的文件,这由参数innodb_file_per_table控制:
-
设为OFF,表示表数据放在系统共享表空间,也就是跟数据字典放在一起;
-
设为ON,表示每个InnoDB表数据存储在一个以
.ibd为后缀的文件中。
从MySQL 5.6.6版本开始,默认值为ON。建议也是使用ON,因为一个表单独存储为一个文件更容易管理,而且在不需要该表时通过drop table命令,系统就会直接删除文件;如果是放在共享表空间中,即使表删除,空间也是不会回收的。
接下来的讨论也是基于innodb_file_per_table=ON的设置。
在删除整张表的时候,可以使用drop table命令回收表空间。但是,平时更多的场景是删除某些行。
数据删除流程
为了搞懂删除部分行的场景,需要先从数据删除流程开始说。
看一下InnoDB中一个索引的示意图:
