13 | 为什么表数据删掉一半,表文件大小不变?
该思维导图由 AI 生成,仅供参考
参数 innodb_file_per_table
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了MySQL中InnoDB引擎下的数据库表空间回收问题,特别是在删除数据后表文件大小未发生变化的情况。首先介绍了InnoDB表的组成结构和参数innodb_file_per_table的作用,建议将该参数设置为ON以便更好地管理表空间。随后详细说明了数据删除流程,包括记录和数据页的复用,以及删除和插入数据可能导致的空洞问题。最后,介绍了通过重建表来收缩表空间的方法,包括使用alter table命令和优化流程。此外,还提到了GitHub开源的gh-ost工具,用于更安全地操作大表的重建。总的来说,本文对InnoDB表空间回收的原理和方法进行了深入浅出的解释,对于处理数据库表空间问题的读者具有一定的参考价值。
《MySQL 实战 45 讲》,新⼈⾸单¥68
全部留言(206)
- 最新
- 精选
- 发条橙子 。置顶老师 , 我的确实是 5.7 版本。我今天看了些关于 online ddl的文章 ,再结合表锁那章评论的内容,有几个点还想确认一下 ,希望老师能解答一下 。 1. 是不是 5.6 之后 所有的 alter 操作(增删字段、增删索引等)都是支持 online ddl 2. 如果 alter 都是 online ddl 那么是不是如果 alter操作 获取到mdl写锁 时, 后面的 查询需要mdl读锁会暂时阻塞, 但是mdl会马上降为读锁 ,后面的操作会继续进行不会堵塞 。等再升到写锁 ,后面操作又会暂时阻塞。 3. 当 alter 降到mdl 读锁时 , 这时候可以新增数据么 , mdl表级读锁 不会影响到 insert 或者 update的行锁么 4. 如果将 alter 操作显式的放到事务里 ,事务不提交 , 另一个事务查询的时候会查询到alter 操作后的表结构 , 比如新增了一个字段。这个是什么原因 ,是否打破了 mvcc 的定义呢
作者回复: 1. 不是哦,我文章里说的加全文索引就不online 2. 对,这两个暂时,都是时间很短的 3. 是,DML语句加的是MDL读锁,读读不冲突 4. 好问题 , 不过alter table 语句会默认提交前面的事务,然后自己独立执行😄
2018-12-13986 - 陈飞置顶老师,请问下分布式ID(雪花算法生成的ID)生成的索引会比自增长的ID性能低吗? 雪花算法生成的ID是越来越大的,但不是逐渐递增,长度用的的bitint,麻烦解答下,非常感谢。
作者回复: 好问题。 性能一样的,没有一定要“连续”,只要是递增
2018-12-136194 - 郜置顶麻烦咨询个问题,“在图 3 中,我们把表 A 中的数据导出来的存放位置叫作 tmp_table。这是一个临时表,是在 server 层创建的。” 在server层创建的表也是将A表数据copy到了临时表,为什么在空间不够用时就没有问题,而inplace在InnoDB执行则会再占用一份存储?
作者回复: 额, Copy的时候肯定更要的… 这里特别指出来,是因为大多数人很容易理解copy需要临时空间,但是误以为inplace不需要 Anyway,好问题 😄
2018-12-13834 - undifined置顶老师,有几个问题: 1.Truncate 会释放表空间吗 2.重建表的时候如果没有数据更新,有没有可能产生页分裂和空洞 3.页分裂是发生在索引还是数据上 4.应用 row log 的过程会不会再次产生页分裂和空洞 5.不影响增删改,就是 Online;相对 Server层没有新建临时表,就是 inplace,这里怎么判断是不是相对 Server 层没有新建临时表 辛苦老师解答一下,谢谢老师
作者回复: 1. Truncate 可以理解为drop+create 2. Online 可以认为没有 3. 数据也是索引哦 4. 可能会 5. 好问题,我放到明天答疑部分
2018-12-1214119 - 飞翔我想到的其中一种可能: 本来就很紧凑,没能整出多少剩余空间。 重新收缩的过程中,页会按90%满的比例来重新整理页数据(10%留给UPDATE使用), 未整理之前页已经占用90%以上,收缩之后,文件就反而变大了。
作者回复: 一个漂亮的答案
2018-12-1219305 - 帆帆帆帆帆帆帆帆@undifined怎么判断是不是相对 Server 层没有新建临时表。一个最直观的判断方法是看命令执行后影响的行数,没有新建临时表的话新建的行数是0。
作者回复: 👍🏿,下一篇答疑直接贴你答案😄
2018-12-12894 - Mr.Panda很喜欢作者的MySQL,绝对干货哈哈。 这里针对空洞提下问题: 1.删除有空洞,是因为标记了已删除可复用的节点位置,不会释放。 2.随机插入有空洞,是因为数据页分裂造成。 3.但更新有空洞,有点费解,我个人理解是更新是结合删除和插入的一个合并操作。删除后产生的空洞,在插入时不是应该就马上被复用了吗,毕竟主键是一致的。所以为什么更新会产生空洞呢??
作者回复: 3. 可以这么想下,如果1,2,3,4,5 然后update把2 改成6, 如果原地修改,这个索引就不是“有序”的了
2019-01-292193 - null临时表插入数据时,不允许表 A 有增删改操作,否则会造成数据丢失。所以表数据 copy 的方式不是 online 的。 而 inplace 的方式,在构建临时文件时,允许表 A 有增删改操作,期间新的增删改操作会记录到另外的日志文件,表 A 数据页的所有数据复制完成后,再应用日志文件(自己理解:应用日志文件时,不允许对表 A 增删改操作,即非 online 的)。整体操作是 online 的。 切换表名或临时文件时,需要获取 MDL 写锁。 inplace 表示在 innodb 引擎完成所有操作,对 server 层是透明的。inplace 操作不一定是 online 的,如 MySQL 8.0 的添加全文索引和空间索引。而 online 的一定是 inplace 的。
作者回复: 👍
2019-02-10459 - wang chen wenoptimize table t 等于 recreate+analyze 老师请教个问题recreate出来应该是几乎全新的,analyze的必要性?
作者回复: 好问题,这个得是比较极端的情况下才有必要,所以我比较喜欢直接用alter
2018-12-12332 - 某、人通过第10期的课后思考题学习到如果delete的数据还会被用于MVCC,那么该数据页(二级索引和聚簇索引)上的记录不会被物理删除,是被标记删除。只有当该事务不会用于mvcc了,才可以被purge线程把之前标记删除的数据真正删除掉.但是即便数据物理删除了,磁盘空间也不会返回给操作系统.可以通过show table status like 't';观察data_free来预估该表的碎片。如果过大,可以用alter table t engine=innodb来清除 我有几个问题请教下老师: 1.inplace相对于其他在线改表软件,多了MDL X锁.既然都是通过临时表/文件来做,为什么一开始要上MDL X锁? 2.gh-ost使用binlog来做同步,假设从position 1开始,先lock S前面1000条数据做cp,这时有事务对后面1000条数据做了修改或者插入。等cp后面这个1000条时,会把修改好的数据cp到临时表.最后又应用binlog,那么这相当于做了两次操作,请问这部分数据是怎么处理的? 3.online会把过程中对表的操作记录在一个(row log)中,那么中途这些DML事务,是怎么判定的commit?我做测试,中途这些事务都是成功的。但是有在做online DDL快完了,commit那个阶段,DDL报唯一键冲突,这又是什么原因造成的啊?我没有模拟出来这个例子
作者回复: 1. 确保没有启发请求在用这个表 2. Binlog设置为row格式,幂等的 3. 这个我觉得其实是bug,就没提。你在DDL期间,往原表插入一个已经存在相同主键的一行试试
2018-12-13729