美文网首页
13. 删除了空间却没回收, 收缩表空间

13. 删除了空间却没回收, 收缩表空间

作者: 胖达_4b7e | 来源:发表于2019-02-18 00:32 被阅读0次

    一个 InnoDB 表包含两部分,

    • 表结构定义
      在 MySQL 8.0 版本以前,存在以.frm 为后缀的文件里。
      而 MySQL 8.0 版本,则已经允许把 放在 系统数据表中了。

    • 数据
      可以存在共享表空间里,也可以是单独的文件。
      5.6.6 版本开始,它的默认值就单独的文件
      一个表 单独存储为一个文件更容易管理,需要这个表的时候,通过 drop table 命令,系统就会直接删除这个文件。
      而如果是放在共享表空间中,即使表删掉了,空间也是不会回收的。
      遇到的更多的是删除某些行,
      数据被删除了,但是空间却没有被回收

    空洞的形成

    删除:


    要删掉 R4 这个记录,InnoDB 引擎只会把 R4 这个记录标记为删除。如果之后要再插入一个 ID 在 300 和 600 之间的记录时,可能会复用这个位置。但是,磁盘文件的大小并不会缩小。

    如果删掉了一个数据页上的所有记录,页就 标记为可复用

    相邻的两个数据页利用率都很小,系统就会把这两个页上的数据合到其中一个页上,另外一个数据页就被标记为可复用。
    如果整个表的数据删除, 所有的数据页都会被标记为可复用。

    磁盘上,文件不会变小

    插入 :
    如果数据是按照索引递增顺序插入的,那么索引是紧凑的。
    如果数据是随机插入的,就可能造成索引的数据页分裂。 分裂 会造成空洞

    重建表

    空间收缩,为了把表中存在的空洞去掉,
    可以
    新建一个与表 A 结构相同的表 B,然后按照主键 ID 递增的顺序,把数据一行一行地从表 A 里读出来再插入到表 B 中。
    由于表 B 是新建的表,所以表 A 主键索引上的空洞,在表 B 中就都不存在了。
    用表 B 替换 A,从效果上看,就起到了收缩表 A 空间的作用。

    命令是
    alter table A engine=InnoDB 命令来重建表。MySQL 会自动完成转存数据、交换表名、删除旧表的操作。
    MySQL 5.6 版本开始引入的 Online DDL 就是这个复制的过程中 原表可以改

    流程:

    1. 建立一个临时文件,扫描表 A 主键的所有数据页,用数据页中表 A 的记录生成 B+ 树,存储到临时文件中;
      生成临时文件的过程中,将所有对 A 的操作记录在一个日志文件(row log)中,对应的是图中 state2 的状态;

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

    3. 临时文件替换表 A 的数据文件。

    在启动的时候需要获取 MDL 写锁,但是这个写锁在真正拷贝数据之前就退化成读锁了。
    MDL 读锁不会阻塞增删改操作。

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

    相关文章

      网友评论

          本文标题:13. 删除了空间却没回收, 收缩表空间

          本文链接:https://www.haomeiwen.com/subject/pyhoeqtx.html