大家好,我是啊粥,昨天咱们介绍了 MySQL 索引的模型。
文末,我留了一个问题,在咱们执行 delete 命令删除数据的时候,为什么表数据文件大小没变动。
这也是我以前面试遇到过的一个问题,明天就给大家分享一下具体起因。
一般来说,咱们如果想删除整个变的状况下,咱们会间接应用 drop table 来回收表空间,但这是建设在咱们当前不再用这张表时。
然而咱们在业务开发中,更长碰到的是应用 delete 来删除具体的业务数据行,InnoDB 在解决删除的时候会将空间地址标记为删除,然而并不会真正删除。因为它有可能会复用这个地位,所以磁盘文件的大小并不会放大。
比方昨天文章提到的那个个例子,我把那张图再从新贴过来给大家看一下
T4 这条记录被删除后,如果插入一个 ID 是 5 的行,能够间接复用这个空间,不须要再重新分配存储空间。但如果插入的是一个 ID 是 8 的行,就不能复用这个地位了。
删除单条记录,则这个单条记录的空间能够被复用,进一步地,如果咱们用 delete 命令把整个表的数据删除呢?
后果就是,所有的数据页都会被标记为可复用。然而磁盘上,数据文件并不会对应变小,因为它所申请的表空间只不过是被标记为复用,并没有真正回收。
由此咱们得出,delete 命令其实只是把记录的地位,或者数据页标记为了“可复用”,但磁盘文件的大小是不会变的。也就是说,通过 delete 命令是不能回收表空间的。
这些能够复用,而没有被应用的空间,看起来就像是“空洞”。
实际上,不止是删除数据会造成空洞,插入数据也会。如果数据是依照索引递增程序插入的,那么索引是紧凑的。但如果数据是随机插入的,就可能造成索引的数据页决裂。
一般来说,通过大量增删改的表,都是可能是存在空洞的。
所以,如果可能把这些空洞去掉,就能达到膨胀表空间的目标。而重建表,就能够达到这样的目标。
这里,你能够应用 alter table test engine=InnoDB
命令来重建表。在 MySQL 5.5 版本之前,MySQL 会主动实现转存数据、替换表名、删除旧表的操作。
显然,花工夫最多的步骤是往长期表插入数据的过程,如果在这个过程中,有新的数据要写入到表 A 的话,就会造成数据失落。
因而,在整个 DDL 过程中,表 test 中不能有更新。也就是说,这个 DDL 不是 Online 的。
而在 MySQL 5.6 版本开始引入的 Online DDL,对这个操作流程做了优化。我
引入了 Online DDL 之后,重建表的流程
建设一个临时文件,扫描表 test 主键的所有数据页;
用数据页中表 A 的记录生成 B+ 树,存储到临时文件中;
生成临时文件的过程中,将所有对 test 的操作记录在一个日志文件(row log)中;
临时文件生成后,将日志文件中的操作利用到临时文件,失去一个逻辑数据上与表 test 雷同的数据文件;
用临时文件替换表 test 的数据文件。
DDL Online 因为日志文件记录和重放操作这个性能的存在,这个计划在重建表的过程中,容许对表 test 做增删改操作,这也就是 Online DDL 名字的起源。
通过重建表,咱们就能够真正的回收表空间。
总结一下,咱们明天次要分享了为什么在 delete 删除数据的时候,表的数据文件大小并不会产生变动的起因,次要是因为 InnoDB 引擎在解决 delete 删除数据时,会把删除行的地位标记为可复用,而不是真正删除,所以才会呈现这种数据删了然而表文件大小没变的状况。
好了,咱们明天的内容到此结束了,最近两天咱们分享了索引模型是什么,今天开始我会分享 MySQL 中索引具体怎么用。
我是程序员啊粥,关注我,咱们一起在技术陆地中向上成长。