表空洞的产生

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

    如下图所示,这个删除过程只是标记了某行的位置为删除,假如此时在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. Verilog-case、casez和casex的区别

    参考博客:https://www.cnblogs.com/guolongnv/articles/6906929.html 1.基本概念 1)?表示z,而不是“dont care” 2)区分: case ...

  2. AI 所需的数学基础

    一.[微积分] 基础概念(极限.可微与可导.全导数与偏导数):只要学微积分,就必须要明白的概念,否则后面什么都无法继续学习. 函数求导:求导是梯度的基础,而梯度是 AI 算法的基础,因此求导非常重要! ...

  3. python3包、模块、类、方法的认识

    包>>模块>>类>> 函数 包:就是一个目录,import time from+import导入包中的部分模块 直接到类 from budaoguan.common ...

  4. BZOJ3172&&lg3966 TJOI单词(广义后缀自动机)

    BZOJ3172&&lg3966 TJOI单词(广义后缀自动机) 题面 自己找去 HINT 给出多个文本串,让你查找每个文本串一共出现了多少次,广义后缀自动机建出parent tree ...

  5. Java知识点题集

    一.红黑树的特性 (1)每个节点或者是黑色,或者是红色. (2)根节点是黑色. (3)每个叶子节点(NIL)是黑色. [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!] (4)如果一个节 ...

  6. Linux 一些使用工具

    ssh 链接使用工具xshell 下载链接 http://www.onlinedown.net/soft/36383.htm 映射硬盘工具 sftpdriver 安装输入服务器之后链接 并且输入注册码 ...

  7. 在vue项目中设置BASE_URL

    在vue项目中设置BASE_URL 1.在config文件夹中新建global.js文件 const BASE_URL = 'http://192.168.1.62:8080/rest/' expor ...

  8. Ubuntu OS 打开端口命令

    直接执行命令:ufw allow 80 再去修改对应功能配置文件的端口号

  9. (转)HashMap和HashTable源码

    转自: http://www.cnblogs.com/ITtangtang/p/3948406.html http://frankfan915.iteye.com/blog/1152091 一.Has ...

  10. 解决Oracle ORA-01033: ORACLE initialization or shutdown in progress错误 和 ORA-01589错误 要打开数据库则必须使用 RESETLOGS 或 NORESETLOGS 选项

    要打开数据库则必须使用 RESETLOGS 或 NORESETLOGS 选项 SQL> startupORACLE 例程已经启动. Total System Global Area  13533 ...