mysql---什么是OnlineDDL

前言

DDL,即Data Defination Language,是用于定义数据库结构的操作。DDL操作用于创建、修改和删除数据库中的表、索引、视图、约束等数据库对象,而不涉及实际数据的操作。以下是一些常见的DDL操作:

  • CREATE
  • ALTER
  • DROP
  • TRUNCATE

与DDL相对的是DML,即Data Manipulation Language,用于操作数据。即包括我们常用的INSERT、DELETE和UPDATE等。

  • 在MySQL 5.6之前,所有的ALTER操作其实是会阻塞DML操作的,如:添加/删除字段、添加/删除索引等,都是会锁表的。

  • 但是在MySQL 5.6中引入了Online DDL,OnLineDDL是MySQL5.6提出的加速DDL方案,尽最大可能保证DDL期间不阻塞DML动作。但是需要注意,这里说的尽最大可能意味着不是所有DDL语句都会使用OnlineDDL加锁。

Online DDL的优点就是可以减少阻塞,是MySQL的一种内置优化手段,但是需要注意的是,DDL在刚开始和快结束的时候,都需要获取MDL锁,而在获取锁的时候如果有事务未提交,那么DDL就会因为加锁失败而进入阻塞状态,也会造成性能影响。

还有就是,如果Online DDL操作失败,其回滚操作可能成本较高。以及长时间运行的Online DDL操作可能导致主从同步滞后。

但是需要注意的是,即使有了Online DDL,也不意味着就可以随意在业务高峰期进行DDL变更了

DDL算法

在MySQL 5.6支持Online DDL之前,有两种DDL的算法,分别是COPY和INPLACE。

我们可以使用如下SQL指定DDL算法:

sql 复制代码
ALTER TABLE hollis_ddl_test ADD PRIMARY KEY (id) ,ALGORITHM=INPLACE,LOCK=NONE

copy算法原理

  • 1.新建一张临时表
  • 2.对原表加共享MDL锁,禁止原表的写,只允许查询操作
  • 3.逐行拷贝原表数据到临时表,且不进行排序
  • 4.拷贝完成后升级原表锁为排他MDL锁,禁止原表读写
  • 5.对临时表rename操作,创建索引,完成DDL操作

INPLACE算法原理

INPLACE算法是MySQL 5.5中引入的,主要是为了优化索引的创建和删除过程的效率。INPLACE算法的原理是可能地使用原地算法进行DDL操作,而不是重新创建或复制表。

  • 1.创建索引数据字典,
  • 2.对原表加共享MDL锁,禁止原表的写,只允许查询操作
  • 3.根据聚集索引的顺序,查询表中的数据,并提取需要的索引列数据。将提取的索引数据进行排序,并插入到新的索引页中。
  • 4.等待当前表的所有只读事务提交。
  • 5.创建索引结束。

MySQL中的INPLACE其实还可以分为以下两种算法:

  • ●inplace-no-rebuild :对二级索引的增删改查、修改变长字段长度(如:varchar)、重命名列名都不需要重建原表
  • ●inplace-rebuild:修改主键索引、增加删除列、修改字符集、创建全文索引等都需要重建原表。

OnlineDDL算法

前面说过,ALGORITHM可以指定的DDL操作的算法,目前主要支持以下几种:

  • 1.COPY算法
  • 2.INPLACE算法
  • 3.INSTANT算法:MySQL 8.0.12 引入的新算法,目前只支持添加列等少量操作,利用 8.0 新的表结构设计,可以直接修改表的元数据,省掉了重建原表的过程,极大的缩短了 DDL 语句的执行时间。其他类型的改表语句默认使用inplace算法。 关于instant支持的场景可参考官方文档Online DDL Operations
  • 4.DEFAULT:如果不指定ALGORITHM,那么MySQL会自行选择默认算法,优先使用INSTANT、其次是INPLACE、再然后是COPY

以下是MySQL官网上给出的Online DDL对索引操作的支持情况:

OnlineDDL的原理

以下是OnlineDDL的整体步骤,主要分为Prepare阶段、DDL执行阶段以及Commit阶段。

Prepare阶段:

  • 1.创建临时 frm 文件
  • 2.加EXCLUSIVE-MDL 锁,禁止读写
  • 3.根据alter类型,确定执行方式(copy/online-rebuild/online-norebuild)。这里需要注意如果使用copy算法,就不是OnLineDDL了。
  • 4.更新数据字典的内存对象
  • 5.分配row_log对象,记录OnlineDDL过程中增量的DML
  • 6.生成新的临时idb文件

Execute阶段:

  • 1.降级EXCLUSIVE-MDL锁为SHARED-MDL锁,允许读写。
  • 2.扫描原表聚集索引的每一条记录。
  • 3.遍历新表的聚集索引和二级索引,逐一处理。
  • 4.根据原表中的记录构造对应的索引项。
  • 5.将构造的索引项插入sort_buffer 块排序。
  • 6.将sort_buffer块更新到新表的索引上。
  • 7.记录 OnlineDDL 执行过程中产生的增量(oinline-rebuild)。
  • 8.重放row_log 中的操作到新表的索引上(online-not-rebuild 数据是在原表上更新)。
  • 9.重放row_log 中的 DML 操作到新表的数据行上。

Commit阶段:

  • 2.升级到 EXCLUSIVE-MDL 锁,禁止读写。
  • 3.重做 row_log 中最后一部分增量。
  • 4.更新 innodb 的数据字典表。
  • 5.提交事务,写redolog。
  • 6.修改统计信息。
  • 7.rename 临时 ibd 文件,frm 文件。
  • 8.变更完成,释放 EXCLUSIVE-MDL 锁。

Prepare阶段和Commit阶段虽然也加了EXECLUSIVE-MDL锁,但操作非常轻,所以耗时较低。Execute阶段允许读写,通过row_log记录期间变更的数据记录,最后再应用row_log到新表中。最终实现OnLineDDL的效果。

相关推荐
小兔崽子去哪了11 分钟前
微信小程序入门
前端·vue.js·微信小程序
独立开阀者_FwtCoder14 分钟前
# 白嫖千刀亲测可行——200刀拿下 Cursor、V0、Bolt和Perplexity 等等 1 年会员
前端·javascript·面试
不和乔治玩的佩奇20 分钟前
【 React 】useState (温故知新)
前端
那小孩儿21 分钟前
?? 、 || 、&&=、||=、??=这些运算符你用对了吗?
前端·javascript
七月十二24 分钟前
[微信小程序]对接sse接口
前端·微信小程序
小七_雪球25 分钟前
Permission denied"如何解决?详解GitHub SSH密钥认证流程
前端·github
野原猫之助27 分钟前
tailwind css在antd组件中使用不生效
前端
AronTing30 分钟前
10-Spring Cloud Alibaba 之 Dubbo 深度剖析与实战
后端·面试·架构
没资格抱怨33 分钟前
如何在vue3项目中使用 AbortController取消axios请求
前端·javascript·vue.js
掘金酱37 分钟前
😊 酱酱宝的推荐:做任务赢积分“拿”华为MatePad Air、雷蛇机械键盘、 热门APP会员卡...
前端·后端·trae