两种删除数据的场景
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 theinnodb_file_per_table
variable. Disablinginnodb_file_per_table
causesInnoDB
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记录的操作重放应用到新表中,最后再删除原始表。