mysql crud造成数据空洞的原因
作者:互联网
mysql数据空洞
- 删除时,如果重新添加新的数据还在(删除所包含的区间),且不会产生页分裂的情况下,该空洞可以被复用
- 如果数据页写满的时候,会产生页分裂,会产生新的数据空洞 页合并是页分裂的逆过程,当两个相邻页面利用率较低时,会发生页合并。
- 如果数据是按照索引递增顺序插入的,那么索引是紧凑的。但如果数据是随机插入的,就可能造成索引的数据页分裂。
- 另外,更新索引上的值,可以理解为删除一个旧的值,再插入一个新值。不难理解,这也是会造成空洞的。
解决方案
alter table A engine=InnoDB 重建表空间,释放空洞的空间,缩容。
如果要收缩一个表,只是 delete 掉表里面不用的数据的话,表文件的大小是不会变的,你还要通过 alter table 命令重建表,才能达到表文件变小的目的。
MySQL 5.6 之前
要求在整个 DDL 过程中,表 A 中不能有更新。也就是说,这个 DDL 不是 Online 的。 如果在这个过程中,有新的数据要写入到表 A 的话,就会造成数据丢失。
MySQL 5.6 版本开始引入的 Online DDL
引入了 Online DDL 之后,重建表的流程:
- 建立一个临时文件,扫描表 A 主键的所有数据页;
- 用数据页中表 A 的记录生成 B+ 树,存储到临时文件中;
- 生成临时文件的过程中,将所有对 A 的操作记录在一个日志文件(row log)中,对应的是图中 state2 的状态;
- 临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表 A 相同的数据文件,对应的就是图中 state3 的状态;
- 用临时文件替换表 A 的数据文件。
由于日志文件记录和重放操作这个功能的存在,这个方案在重建表的过程中,允许对表 A 做增删改操作。
注意点:Online DDL 其实是会先获取MDL写锁, 再退化成MDL读锁;但MDL写锁持有时间比较短,所以可以称为Online; 而MDL读锁,不阻止数据增删查改,但会阻止其它线程修改表结构;
例子 :对于一个大表来说,Online DDL 最耗时的过程就是拷贝数据到临时表的过程,这个步骤的执行期间可以接受增删改操作。所以,相对于整个 DDL 过程来说,锁的时间非常短。对业务来说,就可以认为是 Online 的。
Online 和 inplace区别
在5.6之前:我们把表 A 中的数据导出来的存放位置叫作 tmp_table。这是一个临时表,是在 server 层创建的。
MySQL 5.6 版本开始引入的 Online DDL之后:根据表 A 重建出来的数据是放在“tmp_file”里的,这个临时文件是 InnoDB 在内部创建出来的。整个 DDL 过程都在 InnoDB 内部完成。对于 server 层来说,没有把数据挪动到临时表,是一个“原地”操作,这就是“inplace”名称的来源。对于server层来说,它是没有生成任何临时文件的,所以叫inplace 它都是在innodb层做的。
两者的区别:如果说这两个逻辑之间的关系是什么的话,可以概括为:DDL 过程如果是 Online 的,就一定是 inplace 的;反过来未必,也就是说 inplace 的 DDL,有可能不是 Online 的。截止到 MySQL 8.0,添加全文索引(FULLTEXT index)和空间索引 (SPATIAL index) 就属于这种情况。
怎么判断是不是相对 Server 层没有新建临时表?
一个最直观的判断方法是看命令执行后影响的行数,没有新建临时表的话新建的行数是0。
alter table t engine=innodb,ALGORITHM=inplace; //原地
alter table t engine=innodb,ALGORITHM=copy;//拷贝
与inplace在引擎层创建tmp文件不同,copy需要在server层建临时表
标签:table,mysql,DDL,crud,inplace,空洞,Online,临时文件,数据 来源: https://blog.csdn.net/qq_29066533/article/details/113532109