Mysql删除数据对磁盘空间的影响

Posted by KANG's BLOG on Monday, April 11, 2022

两种删除数据的场景

Mysql删除数据分两种场景,其删除数据时对磁盘的影响不同。

DROP TABLE …

DROP TABLE时,会将表结构信息和数据一起删除,但这时就要看该表数据是存储在独立文件中(File-Per-Table)还是系统空间(亦称为共享表空间)中。

如果是在独立文件中,那么DROP成功后将直接删除数据,而系统空间中,即使表删掉也不会回收空间。

先来看看mysql官网上对File-Per-Table概念的解释:

A file-per-table tablespace contains data and indexes for a single InnoDB table, and is stored on the file system in a single data file.

InnoDB creates tables in file-per-table tablespaces by default. This behavior is controlled by the innodb_file_per_table variable. Disabling innodb_file_per_table causes InnoDB to create tables in the system tablespace.

InnoDB默认创建表时会将表数据单独存在独立的文件中,通过innodb_file_per_table属性可以控制该行为,如果将其设为OFF,那么将在系统的表空间中创建表。

mysql> SET GLOBAL innodb_file_per_table=ON;

DELETE FROM …

DELETE命令只是把记录的位置或者数据页标记为“可复用”,所以不会对磁盘空间有任何影响。

重建表

当数据被删除,或者新增数据发生页分裂时,会造成很多空间被标记为“可复用”,这些“空洞”就是数据库的碎片化问题所在。当存在太多空洞,导致磁盘空间占用过大时,可以使用alter table A engine=InnoDB命令来重建表使得空间利用率增加。

原理是,复制出与原表A相同表结构的表B,再把A中叶子节点中的所有数据顺序读取出来插入到B表中,完成后删除表A。由于表B是顺序插入的新表,所以不存在空洞问题。但是复制数据的过程中,需要阻塞对表A的数据插入或者更新,所以在MySQL 5.6版本引入了Online DDL,主要差别在于复制数据时,对A的操作将记录在一个日志文件(row log)中,当数据复制完成后,将row log记录的操作重放应用到新表中,最后再删除原始表。