暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

MySQL Online DDL

原创 进击的CJR 2023-06-14
4425

一、分类


在MySQL5.6版本之后,进行 DDL 可选择执行方式
可以通过aLter table 时添加 ALGORITHM参数控制使用算法。

例如:

alter table t3 add index idx_name(name1) , ALGORITHM INPLACE/COPY/DEFAULT;
alter table hank add column name1 varchar(16),ALGORITHM INPLACE/COPY/DEFAULT;


目前可以支持的主流算法有三种:
COPY      —— MySQL 5.6之前非Online,都是执行这种算法
INPLACE —— MySQL 5.6出现的
INSTANT —— MySQL 8.0.12出现的


二、Copy


准备(prepare)

1.对元数据进行添加共享锁(MDL-S)[Meta Data Lock Share],读取原表结构。(不能进行DDL,不阻塞DML,但是过程很短)
2.S锁升级为X锁(共享锁升级为排他锁),此时阻塞DDL、DML。
3.创建和原表一致的临时表。server层会执行类似create table的语句来创建一个和表结构一致的临时表,在引擎层也会生成frm和ibd文件。(8.0之后没有.frm文件)


执行(run)

4.修改新创建的临时表的表结构。
5.临时表的表结构修改完成之后,server层copy原来表数到到临时表中(阻塞DML,阻塞的时间取决于拷贝的速度)表一旦过大,受拷贝数据到临时表的影响。
6.server层替换两个表(重命名临时表及文件),修改原来的文件,然后然后将临时文件名修改成原文件名。
7.删除原表所有数据。


提交(commit)

8.commit,释放所有锁。


 

1.从开始,一直到执行结束,都是上锁(MDL-X)的,阻塞所有的DDL和修改类的DML,大多数情况下SELECT操作不会被阻塞。
2.此类操作不是online DDL,在执行整个DDL阶段(执行阶段)都是阻塞业务的。



三、Inplace


在MySQL5.6 出现的新算法,无需拷贝全表数据到新表,但可能还是需要INPLACE方式(原地,无需生成新的临时表)重建整表。这种情况下,在DDL的初始准备和最后结束两个阶段时通常需要加排他MDL锁(metadata lock,元数据锁),除此外,DDL期间不会阻塞DML。


准备(prepare)

准备阶段阻塞DML
0.在进入prepare阶段前对元数据持有可升级的S锁(MDL-S锁),在此阶段不允许DML, 不允许部分ddl。
1.在预备阶段MDL-S锁会升级为X锁(排他锁),在此时会判断,操作是否需要rebuild table。
2.判断是需要rebuild table还是no rebuild table,判断完之后进行下一步,如果需要rebuild table,则申请row log空间。


重点说明

判断使用inplace算法
判断语句是“rebuild table” 还是 “no-rebuild”
如果需要rebuild table,则需要在engine层生成原表的转储文件(比如:ibd,frm文件,DDL阶段执行)。
【在引擎层克隆,而不是像copy那样,在server层创建(create like),创建ibd转储文件的操作,需要额外的存储空间】
如果是no reduild table,则要在engine层则只需要生成frm文件(比如加索引就是no rebuild table,只需要生成frm,DDL阶段执行。 注:no-rebuild是否使用临时文件: 除创建二级索引外只创建.frm文件,其中添加二级索引操作最为特殊,该操作属于no-rebuild不会生成.ibd, 但实际上对.ibd文件却做了修改,该操作会在参数tmpdir指定路径下生成临时文件,用于存储索引排序结果,然后再合并到.ibd文件中 row log作用:记录online DDL执行阶段,对原表数据做的DML操作的。(row log由innodb_sort_buffer_size决定)。 注意:加列的操作是需要rebuild table的,这个在8.0中有优化,这里需要提一下



执行(run)

DDL执行阶段不阻塞DML 。
3.执行阶段 会把X锁降级为S锁,该阶段不阻塞dml操作 ,这个阶段被称为online阶段,例如在加列过程中可能时间比较长,在这期间大部分时间是不阻塞DML操作
4.MDL-X锁降级为MDL-S锁,将原表存储的数据读取到prepare阶段创建的ibd文件中(engine层完成,直接分析数据页,内部结构,将原表的数据记录逐行取出后进行处理,且会执行ddl修改表结构,并应用到新的ibd文件中)

在负载、IO上可能会有点影响 。


提交(commit)

commit阶段阻塞DML
5.提交阶段engine层应用row log中的操作到新的ibd文件中直到最后一个,系统会自动判断进行截断,避免源源不断的DML操作。
6.此时MDL-S锁再此升级到MDL-X锁(拒绝所的DML),然后把row log中剩余的数据应用完。
7.删除原表,替换新表为原表( 最后将临时文件替换为原文件,清理老文件)。
8.最后提交。



 


INPLACE重点注意


(1)在DDL期间产生的数据,会按照正常操作一样,写入原表,记redolog、undolog、binlog,并同步到从库去执行,只是额外会记录在row log中,并且写入row log的操作本身也会记录redolog

(2)在提交阶段才进行row log重做,此阶段会锁表,此时主库(新表空间+row log)和从库(表空间)数据是一致的,在主库DDL操作执行完成并提交,这个DDL才会写入binlog传到从库执行,在从库执行该DDL时,这个DDL对于从库本地来讲仍然是online的,也就是在从库本地直接写入数据是不会阻塞的,也会像主库一样产生row log。

(3)但是对于主库同步过来DML,此时会被阻塞,是offline的,DDL是排他锁的在复制线程中也是一样,所以不只会阻塞该表,而是后续所有从主库同步过来的操作(主要是在复制线程并行时会排他,同一时间只有他自己在执行)。所以大表的DDL操作,会造成同步延迟。


用户角度看online ddl,在执行ddl期间,不阻塞DML操作。
管理员角度看online ddl
准备阶段 持有X锁      ->阻塞DML
执行阶段 降级为S锁    ->不阻塞DML
提交阶段 升级为X锁    ->阻塞DML


四、Instant


只需修改数据字典中的元数据,无需拷贝数据也无需重建整表,同样,也无需加排他MDL锁,原表数据也不受影响。整个DDL过程几乎是瞬间完成的,也不会阻塞DML。

这个新特性是8.0.12引入的(腾讯DBA团队贡献)。执行DDL操作时,ALGORITHM选项可以不指定,这时候MySQL按照INSTANT、INPLACE、COPY的顺序自动选择合适的模式。也可以指定ALGORITHM=DEFAULT,也是同样的效果。如果指定了ALGORITHM选项,但不支持的话,会直接报错。

当采用COPY模式时,这时表里任何的修改数据操作,DDL都会被阻塞。COPY模式下会生成临时新表,操作完成后原表会被删除,新表被重命名为原表名。当DDL开始后,原表上仅能只读,其他的DML操作也都会被阻塞。COPY过程中,唯一会阻塞只读的时机是在清理旧表结构和表定义缓存时。

MySQL 8.0.12 才提出的新算法,目前只支持添加列等少量操作(添加列(追加)、更改索引选项、重命名表(以ALTER方式)、设置/删除默认值、修改栏、添加/删除虚拟列还不是太成熟,企业中一般都是5.6、5.7版本),利用 8.0 新的表结构设计,可以直接修改表的 metadata 数据,省掉了 rebuild 的过程,极大的缩短了 DDL 语句的执行时间。



五、总结


COPY     ——  5.6之前默认适应这种方法,全程无法并行DML
INPLACE —— MySQL 5.6出现的,在开始和提交的短租时间里,不能并行DML
INSTANT —— MySQL 8.0.12出现的,唯一会阻塞只读的时机是在清理旧表结构和表定义缓存时。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
2人已赞赏
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论