表空洞的产生

删除某个行数据 或删除某个页

    如下图所示,这个删除过程只是标记了某行的位置为删除,假如此时在300与600之间插入了一行数据,那么

同理,当删除某个页时,该页就会被复用。所以当删除某一行或页时空间并不会被回收,而是会被复用,这些可以复用,而没有被使用的空间,看起来就像是“空洞”。

插入数据产生空洞

    不仅是删除数据,插入数据的时候也会产生空洞,

    例如上图,插入一行索引为550 的记录,经过页分裂后会产生新的页,而旧的pageA 会产生页空洞,如果能够把这些空洞去掉,就能达到收缩表空间的目的。而重建表就,就可以达到这样的目的。

表空洞优化过程

重建表

MySQL5.5之前(不是Online的)

    重建表的作用是使我们的空间更加紧凑,提高空间的利用率,你可以想到的方法应该是使用一张临时表,将表的数据条条从久表迁移过去,然后新表替换久表就行了。这里,你可以使用alter table A engine=InnoDB命令来重建表。在MySQL 5.5版本之前,这个命令的执行流程跟我们前面描述的差不多,区别只是这个临时表B不需要你自己创建,MySQL会自动完成转存数据、交换表名、删除旧表的操作。
    操作如下 :

    需要注意的是当表在重建的时候,是不允许DDL 的!

MySQL5.5以后(是Online的)

    MySQL5.5以后的重建表操作,此时要是有DDL操作,先会记录到日志文件中去,之后再运用在新文件中,具体的过程如下 :

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

  2. 用数据页中表A的记录生成B+树,存储到临时文件中;

  3. 生成临时文件的过程中,将所有对A的操作记录在一个日志文件(row log)中,对应的是图中state2的状态;

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

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

操作如下 :

这样即是表在重建的过程中,依旧可以DDL.

底层实现小疑问

问题: DDL之前是要拿MDL写锁的,这样还能叫Online DDL吗?
下面解答来自参考资料

    确实,图4的流程中,alter语句在启动的时候需要获取MDL写锁,但是这个写锁在真正拷贝数据之前就退化成读锁了。

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

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

而对于一个大表来说,Online DDL最耗时的过程就是拷贝数据到临时表的过程,这个步骤的执行期间可以接受增删改操作。所以,相对于整个DDL过程来说,锁的时间非常短。对业务来说,就可以认为是Online的。

需要补充说明的是,上述的这些重建方法都会扫描原表数据和构建临时文件。对于很大的表来说,这个操作是很消耗IO和CPU资源的。因此,如果是线上服务,你要很小心地控制操作时间。如果想要比较安全的操作的话,我推荐你使用GitHub开源的gh-ost来做。

参考资料

  • 《MySQL45讲》

MySQL学习(八)删除表数据的更多相关文章

  1. mysql 清空或删除表数据后,控制表自增列值的方法

    http://blog.sina.com.cn/s/blog_68431a3b0100y04v.html 方法1: truncate table 你的表名 //这样不但将数据全部删除,而且重新定位自增 ...

  2. mysql语句中----删除表数据drop、truncate和delete的用法

    程度从强到弱 1.drop  table tb        drop将表格直接删除,没有办法找回 2.truncate (table) tb       删除表中的所有数据,不能与where一起使用 ...

  3. Mysql定时器定时删除表数据

    由于测试环境有张日志表没定时2分钟程序就狂插数据,导致不到1一个月时间,这张日志表就占用了6.7G的空间,但是日志刷新较快,有些日志就没什么作用,就写了个定时器,定期删除这张表的数据 首先先查看mys ...

  4. mysql进阶(二十一)删除表数据

    MySQL删除表数据 在MySQL中有两种方法可以删除数据,一种是DELETE语句,另一种是TRUNCATE TABLE语句.DELETE语句可以通过WHERE对要删除的记录进行选择.而使用TRUNC ...

  5. 针对mysql delete删除表数据后占用空间不变小的问题

    开发环境 Yii1版本 MySQL PHP5.6.27 前言 物流规则匹配日志表记录订单匹配规则相关日志信息,方便管理员维护和查阅不匹配的订单,四个月时间,该日志表数据就有174G,当前,这么大的数据 ...

  6. MySQL学习——查询表里的数据

    MySQL学习——查询表里的数据 摘要:本文主要学习了使用DQL语句查询表里数据的方法. 数据查询 语法 select [distinct] 列1 [as '别名1'], ..., 列n [as '别 ...

  7. MySQL学习——操作表里的数据

    MySQL学习——操作表里的数据 摘要:本文主要学习了使用DML语句操作表里数据的方法. 插入数据 语法 通过传入数据插入: insert into 表名 [(列名1, …, 列名n)] values ...

  8. MySQL 中国省市区SQL表数据

    MySQL 中国省市区SQL表数据   1.查省SELECT * FROM china WHERE china.Pid=02.查市SELECT * FROM chinaWHERE china.Pid= ...

  9. sql 删除表数据并使ID自增重置

    方法1:truncate table 你的表名//这样不但将数据全部删除,而且重新定位自增的字段 方法2:delete from 你的表名dbcc checkident(你的表名,reseed,0)  ...

  10. sql语句中----删除表数据drop、truncate和delete的用法

    sql语句中----删除表数据drop.truncate和delete的用法 --drop drop table  tb   --tb表示数据表的名字,下同 删除内容和定义,释放空间.简单来说就是把整 ...

随机推荐

  1. windows密码抓取工具-mimikatz

    前言 介绍一下windows的密码hash值的组成: Windows系统下的hash密码格式为:用户名称:RID:LM-HASH值:NT-HASH值,例如: Administrator::C8825D ...

  2. 归并排序 ALDS1_5_B:Merge Sort

    Merge Sort Write a program of a Merge Sort algorithm implemented by the following pseudocode. You sh ...

  3. UTF自动化测试工具

    自UFT推出后,QTP慢慢退出历史舞台 UFT测试的基本流程:录制测试脚本—-编辑测试脚本—-调试测试脚本—-运行测试脚本—-分析测试结果 UFT(QTP)介绍   http://blog.csdn. ...

  4. 推荐7个GitHub项目

    CS-Notes https://github.com/CyC2018/CS-Notes 技术面试必备基础知识.Leetcode.计算机操作系统.计算机网络.系统设计.Java.Python.C++. ...

  5. [TJOI2013] 拯救小矮人- 贪心,dp

    结论:矮的人比高的人先走一定不会使得答案变劣 于是我们排序后,像 0-1 背包那样依次考虑每个人走不走 #include <bits/stdc++.h> using namespace s ...

  6. USACO06DEC 牛奶模式

    题意:求最长的可重叠的 K重复子串 的长度 考虑二分长度s,转化为验证性问题. 对SA进行分组.保证组内Height最小为s.这样在组内RMQ就可以任意了,因为RMQ一定是大于S的. 只要组内元素个数 ...

  7. Ubutu安装oracle jdk1.8

    环境: Ubuntu 18.04 LTS x64位 系统用户  hou 工具: jdk-8u171-linux-x64.tar.gz 实验的心 步骤: 第一步: 查看有没有装jdk,按住  ctr+a ...

  8. PP: Multilevel wavelet decomposition network for interpretable time series analysis

    Problem: the important frequency information is lack of effective modelling. ?? what is frequency in ...

  9. Bootstrap框架中radio设置值

    Bootstrap中的radio设置值不能像我们平常给普通radio赋值那样,因为无效. 我们用Bootstrap框架里的radio组件,代码: <div class="radio-l ...

  10. 解决Maven依赖报红的批处理文件

    maven经常因为网络或者其他原因导致仓库jar包下载不完整,导致jar包依赖报红,此小工具可以一键删除未下载完成文件 set REPOSITORY_PATH=E:\deplor\apache-mav ...