本文正在参加「金石计划」
hello,咱们好,我是张张,「架构精进之路」公号作者。
1、应用布景
在日常工作开发中,在MySQL中,如果咱们对大表频频进行insert和delete操作,那么时间一长,这个表中会呈现许多”空洞”,也便是表碎片。
碎片发生的原因是insert随机值作为主键id,会发生许多数据页分裂操作;而delete掉一些排列有序的主键值,这些被delete的空间不会直接开释,而是只是进行delete的符号,这些空间如果不能被利用,那就会变成”空洞”。
2、重建表
关于重建表,这时候新建一张结构相同的暂时表,把表内的数据导入到暂时表,直接删去旧表,然后将暂时表替换为旧表,然后开释这些空余的空间,让数据变得”紧凑些”,完成重建操作。
咱们其实能够经过如下指令来重建表:
alter table tableName engine=innodb
在MySQL5.5版别之前,这个指令的履行流程跟1操作差不多,差异只是在于这个暂时表不需求你直接创立,MySQL会自动完成转存数据、交流表名、删去旧表的操作。
这个重建表的进程,在MySQL5.5之前,它的履行逻辑是下面这样的:
1、假定原表是A,新建一个表table B,和表A的表结构保持一致;
2、依照主键次序,将表A的数据一行一行的读出来,插入到表B里边;
3、交流表A和表B的称号。
3、重建实现优化
经过上面的介绍能够发现,花时间最多的步骤是往暂时表插入数据的进程,如果在这个进程中,有新的数据要写入到表 A 的话,就会形成数据丢掉。
因而,在整个 DDL 进程中,旧表中不能有更新(也便是说,这个 DDL 不是 Online 的)。
在MySQL5.6及以后的版别里边,引入了Online DDL的方法,Online DDL的引入,使得上面的进程有了一点点不同,当履行如下指令的时候:
alter table tableName engine=innodb
MySQL5.6版别开始引入的Online DDL,对这个操作流程做了优化:
1、树立一个暂时文件,扫描表A主键的一切数据页;
2、用数据页中表A的记录出产B+树,存储到暂时文件中;
3、出产暂时文件的进程中,将一切对A的操作记录在一个日志文件(row log)中,对应的是图中state2的状况;
4、暂时文件生成后,将日志文件中的操作应用到暂时文件,得到一个逻辑数据上与表A相同的数据文件,对应的便是图中state3的状况;
5、用暂时文件替换表A的数据文件。
履行alter语句时,需求获取MDL写锁,可是这个写锁在真正复制数据之前就退化成读锁。为了实现Online,MDL读锁不会堵塞增删改操作。
那为什么要从写锁退化成读锁而不干脆直接免除锁呢?为了维护自己,制止其他线程对这个表同时做DDL。
4、答疑解惑
关于重建表,信任咱们还会有其他的疑问,一同来总结下。
Q1、在MySQL5.5之前,咱们运用暂时表作为重建的中心介质,在MySQL5.6之后,咱们运用暂时文件作为重建的中心介质,暂时表和暂时文件的差异是?
A:暂时表是创立在server层面的,暂时文件是创立在innodb层面的,所以Online DDL的整个进程都是在Innodb内部完成的,这种方法也称之为”inplace”,相对应的,需求凭借server层面暂时表的进程,称之为”Copy”。
Q2、假定咱们有一个1TB的表,磁盘只要1.2TB,那么还能够做inplace的DDL呢?
A:不能够,由于inplace计划中的暂时文件也要占用一定的空间。
Q3、inplace 计划进行的表重建操作,都是Online DDL么?
A:纷歧定,例如增加全文索引的操作,这个操作是inplace的,可是会堵塞增删改查操作,因而不是Online DDL。应该说:Online DDL一定是inplace的,可是inplace计划进行的操作,纷歧定是Online的。
Q4、某个表的大小是1TB,进行alter table A engine=Innodb之后,表的空间没有缩小,反而增大了一点,这是为什么?
A:或许是由于表之前刚刚进行过一次alter table的操作,并且表上面的并发增删改比较多,在进行alter table 的进程中,这些操作都写进了log中,然后导致表的实践大小会增加。
– END –
Thanks for reading!
作者:架构精进之路,十年研发风雨路,大厂架构师,CSDN 博客专家,专心架构技能沉积学习及分享,工作与认知晋级,坚持分享接地气儿的干货文章,等待与你一同生长。
关注并私信我回复“01”,送你一份程序员生长进阶大礼包,欢迎勾搭。