美文网首页Java技术问答
13 | 为什么表数据删掉一半,表文件大小不变?

13 | 为什么表数据删掉一半,表文件大小不变?

作者: hedgehog1112 | 来源:发表于2019-08-22 18:02 被阅读3次

     InnoDB 表包含:表结构和数据。8.0 前,表结构存在.frm 文件8.0 版本,表结构(占用空间小)放系统数据表

    一、为什么删除表数据,表空间不能回收?

    1.参数innodb_file_per_table

    控制表数据可以存在共享表空间里,也可以是单独的文件。

    1. OFF ,数据共享表空间,跟数据字典一起;表删掉空间不会回收

    2. ON (默认),存在 .ibd 文件中;不需要时, drop table直接删除

    删除行,数据被删除了,空间没有回收。

    2.数据删除流程

    索引的示意图。B+ 树

    图 1 B+ 树索引示意图

    删掉 R4,把 R4 标记为删除。插入ID 300 和 600 复用。磁盘文件大小不变

    InnoDB 数据按页存储,删掉页上所有整个页复用

    3.数据页跟记录复用是不同

    记录复用:插入 ID = 800 ,不能复用

    整页:从 B+ 树里摘掉,可复用任何位置

    两页利用率都小,合到一个,另一页标记为可复用。

    delete 只标记“可复用”,没被用空间,像“空洞”。

    4、插入也会造成空洞

    按索引递增插凑),随机插(页分裂

    图 2 插入数据导致页分裂

    page A 已满,再插,申请新页 page B 保存。页分后,A 末尾留空洞(实际上不止 1 个记录位是空洞)。

    更新:删旧值,插新。也会造空洞

    二、 回收空间:重建表

    新建表 B(表 A 相同结构),A 中读出插入 B (按主键 ID 递增)。

    B 是新建的, A 上空洞, B 不存在(主键索引紧凑)。 B 替换 A收缩表作用。

    alter table A engine=InnoDB 命令重建表。MySQL 5.5 前,B 不需创建,MySQL 会自动完成转存数据、交换表名、删除旧表的操作。

    临时表插入数据(时间最多),期间新写入,到A 数据丢失。DDL中A 中不能更新(非Online)

    图 3 改锁表 DDL

    2、Online DDL( 可做增删改)重建表流程:

    1.  建立临时文件,扫描表 A 主键所有数据页

    2.  A 记录生成 B+ 树,存储临时文件中;

    3.  生成临时文件的过程中, A 操作记录日志文件(row log)中,state2 状态;

    4. 临时文件生成后日志文件操作应用临时文件,逻辑数据上与A 相同,state3 状态;

    5.  临时文件替换表 A。

    图 4 Online DDL

    第 6 篇《全局锁和表锁 :给表加个字段怎么索这么多阻碍?》留言说,DDL 之前拿 MDL 写锁,还能叫 Online DDL 吗?

    alter 启动获 MDL 写锁拷贝数据前退化成读锁(图 4 )。

        为什么退化?实现 Online,MDL 读锁不阻塞增删改操作。

        不解锁,保护自己,禁止其他线程做 DDL。

    拷贝数据最耗时,可以接受增删改。 DDL 过程,锁时间非常短,可认为 Online

    上述重建方法都扫描原表、构建临时文件。对大表来说,很消耗 IO 和 CPU 资源。线上服务,小心控制操作时间。用 GitHub 开源gh-ost 来做安全。

    3.Online inplace

    inplace 和DDL 有关、容易和Online混淆 

    图 3 表 A 中数据导出来放 tmp_table(临时表), server 层创建。

    inplace:重建数据放“tmp_file”里(图 4 ),InnoDB 内部创建。DDL 在 InnoDB 内部完成server 层“原地”操作(没把数据挪动到临时表)。

    例1:1TB 的表,磁盘间 1.2TB,不能做 inplace  DDL ,tmp_file 占临时空间。

    alter table t engine=InnoDB,隐含意思:

    alter table t  engine=innodb, ALGORITHM=inplace;

    对应强制拷贝表(图 3)用法是:

    alter table t  engine=innodb,ALGORITHM=copy;

    例2:给 InnoDB 表字段加全文索引(过程 inplace ,非 Online )

    alter table t add  FULLTEXT(field_name);

    两个逻辑关系是:

    1.  DDL 过程如 Online ,一定 inplace

    2.  反过来未必, inplace 的 DDL,可能不是 Online 。如:添加全文索引(FULLTEXT index)和空间索引 (SPATIAL index) 。

    4.analyze table 和 alter table 、optimize table重建表区别

    alter table t engine = InnoDB(recreate)图  4 ;

    analyze table t 表索引重新统计,没修改数据,过程加了 MDL 读锁;

    optimize table t 等于 recreate+analyze。recreate几乎全新,analyze必要小极端情况用

    小结

    数据库中收缩表空间方法

    收缩一个表,delete 数据表文件大小不变alter table 重建表文件变小

    重建表两种实现:Online DDL业务低峰期使用

    思考题

    收缩表空间,适得其反”什么原因 ?

    表 t 1TB;执行 alter table tengine=InnoDB;变成 1.01TB

    答:表本身没空洞(如刚重建表)。DDL 时,刚好外部 DML 执行,引入新空洞。

    重建表后不是“最”紧凑:重建表时,InnoDB 不会把整张表占满,留1/16 给后续更新。

    如:1.  表 t 重建; 插入数据,掉预留空间;2.  再重建表 t,上面现象。

    评论1

    1.Truncate 会释放表空间吗?理解为drop+create

    2.重建没更新,有可能产生页分裂和空洞Online 没有

    3.相对 Server层没有新建临时表,就是 inplace,怎么判断是不是相对 Server 层没有新建临时表

    命令执行后影响行数,没有新建临时表,新建行数0

    4.分布式ID(雪花算法生成的ID)生成的索引自增ID。性能一样

    雪花算法生成ID:越来越大,但不逐渐递增,长度bitint。

    评论2

    将 alter 显式放到事务里 ,事务不提交 , 另一事务查询到alter 操作后表结构 是否打破了 mvcc ?

    alter table 默认提交前面事务,自己独立执行

    相关文章

      网友评论

        本文标题:13 | 为什么表数据删掉一半,表文件大小不变?

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