Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • MySQL

    • 基础部分

      • 初识MySQL
      • 基础架构&日志
      • 事务隔离
      • 全局锁、表锁、行锁
      • 事务的隔离性和行锁
      • 索引
      • 索引深入(中)
      • 内存脏页刷盘
      • 数据库表的空间回收
        • 1.数据删除插入流程
        • 2.重建表
          • 2.1COPY
          • 2.2Inplace
          • 2.3Online DDL
        • 3.总结
      • count
      • order by
      • SQL语句性能差异分析
      • 幻读与间隙锁
      • 加锁规则案例分析
      • binlog和redolog如何写入磁盘
      • MySQL一致性与高可用性
      • kill命令
      • 全表扫描与内存占用
      • join
      • 临时表与内存表
      • 自增主键
      • insert操作加锁场景分析
      • grant
      • 分区表
      • 思维导图
    • 实战与处理方案

    • 面试

  • ORM框架

  • 数据库
  • MySQL
  • 基础部分
phan
2023-06-20
目录

数据库表的空间回收

# 数据库表的空间回收

innodb_file_per_table:控制表数据的存在形式。设置为ON表示数据存放在.ibd为后缀的文件中。设置为OFF表示数据存放在共享表空间,这种情况下即使表删除了空间不会回收。因此一般情况下推荐设置为ON。

# 1.数据删除插入流程

无论是删除还是插入,数据更新后表空间处于可复用但是还未被使用的空间,都属于“空洞”。这些空洞尚未被InnoDB释放回收,从而导致数据页空间利用率比较低。

  • 删除

复用:无论是删除innoDB索引树上的一条记录,还是删除一个数据页上的所有记录。InnoDB并不会直接将整行记录或者整个数据页都删除,而是在这条记录的位置或者这个数据页上标记为“可复用”,这样新的数据插入后直接使用原本的空间即可。

其中行复用和页复用的区别在于,新插入行复用位置的记录ID,会受到原先位置记录的约束。而页复用则不受任何数据索引或者是主键的限制。

  • 插入

举个例子,原先数据页中某条记录,由于插入新的记录导致数据页分裂,与新记录合并存放到新的数据页。此时该条数据原先所在的位置就是数据空洞。

# 2.重建表

重建表:新建一张表,将旧的存在多个空洞的表数据全部一行一行拷贝到新表当中。显然得到的新表中数据页利用率更高,并且主键索引更加紧凑。下面介绍三种重建表的策略。

DDL:由于执行DDL语句后可能会修改表的结构,因此会触发“重建表”整个过程。

# 2.1COPY

alter table t engine =innodb,ALGORITHM=copy
1

在service层创建一个临时表来对数据进行拷贝,最后用临时表替换原表。

在整个过程中表A仅允许读操作,阻塞所有DML更新写操作。由于需要消耗额外的数据空间,因此仅适用于数据量比较小的场景。

# 2.2Inplace

alter table t engine =innodb,ALGORITHM=inplace
1

在InnoDB内部创建临时文件tmp_file进行修改复制(这里可以近似看作是原地修改表的字段),整个DDL过程都是在InnoDB内部进行。对于server层而言并没有将数据挪动到临时表,相当于原地操作。

这里要注意,说是“原地修改”,实际上临时文件也需要占用一定的磁盘空间。适用于大表修改的场景。

# 2.3Online DDL

重建表时如果有新的数据要写入,会导致数据丢失,因此引入Online DDL对操作流程进行优化,整个过程如下:

  • 执行DDL语句前,获取MDL写锁。

  • 🔥拷贝数据之前,MDL写锁退化为MDL读锁,从而保证在执行DDL和拷贝时,不会阻塞其它线程的DML增删改操作。这就是Online名称的由来。

  • 创建一个临时文件,根据A表中主键数据页的有效记录生成B+树,记录到临时文件中。此时表是最紧凑的。

  • 此时如果要写入数据,写入到旧的A表后,统一将所有操作记录在一个row log文件当中。

  • 临时文件生成完后,按顺序进行以下两个步骤:

    • ①将MDL读锁升级到MDL写锁,为接下来重放更新操作做准备,此时一定要控制多并发DML。

    • ②将row log所有写操作应用到临时文件中。此时临时文件表数据时最新的,但是并不一定是最紧凑的,因为往表中插入新的数据后可能产生新的空洞。

  • 将临时文件代替表A的数据文件。

区别与联系:显然online DDL用到了临时文件,因此online一定是inplace的。反之inplace不一定是online可多并发DML的,比如全文索引。

# 3.总结

要想达到真正的删除表并且释放空间,需要delete+alter,或者truncate(drop+create)

编辑 (opens new window)
#数据库
上次更新: 2023/12/15, 15:49:57
内存脏页刷盘
count

← 内存脏页刷盘 count→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式