MySQL 8.0 DDL 三种算法对比:COPY、INPLACE 与 INSTANT 的业务影响

梳理 MySQL 8.0 DDL 三种算法及其锁影响、耗时和生产风险。

冷月清谈:

文章围绕 MySQL 8.0.25 InnoDB 的三类 DDL 执行算法展开:COPY、INPLACE、INSTANT。COPY 是传统全表拷贝方式,兼容性强但会长时间持有排他锁,大表上容易造成业务阻塞;INPLACE 在引擎层完成结构变更,多数阶段允许并发读写,但提交阶段仍可能因 MDL 锁、长事务或 Row Log 限制带来风险;INSTANT 则主要修改元数据,不扫描数据页,通常毫秒级完成,对业务影响最小。文章还梳理了常见 DDL 操作的默认算法选择、VARCHAR 扩容的字节边界问题、百 GB 级表上的执行时长差异,以及生产环境中需要关注的 INSTANT 次数限制、静默降级、MDL 锁队列、磁盘空间和在线 DDL 工具选型等风险点。

怜星夜思:

1、生产环境做大表 DDL 时,你们会优先相信 MySQL 原生 Online DDL,还是更倾向用 pt-osc、gh-ost 这类工具?
2、INSTANT DDL 看起来几乎无成本,那是不是以后加字段、删字段都可以放心随便做?
3、文章提到 MDL 锁链式阻塞,你们线上遇到过类似问题吗?通常怎么排查和止血?
4、VARCHAR 扩容跨字节边界可能触发 COPY,这种细节你们在表设计阶段会提前考虑吗?

原文标题:数据库DDL算法介绍及业务影响分析

原文作者:牧羊人的方向

原文内容

MySQL 8.0.25版本InnoDB存储引擎支持COPY、INPLACE、INSTANT三种DDL执行算法,三种算法在实现机制、执行效率、锁粒度和业务影响方面存在显著差异。本文简要介绍这三种算法的实现原理、常见的DDL操作默认使用哪种算法以及业务影响如何。

1、DDL三种算法概述

MySQL的ALTER TABLE等DDL操作经历了三个阶段的演进:

阶段
版本
能力
全表拷贝
≤ 5.5
所有DDL均需重建表,执行期间阻塞读写
Online DDL
5.6 ~ 5.7
引入Inplace算法,多数DDL执行期间允许并发DML
Instant DDL
8.0.12+
引入Instant算法,纯元数据变更,毫秒级完成

在MySQL 8.0.25版本的InnoDB存储引擎中,支持三种DDL执行算法:COPY、INPLACE、INSTANT。三种算法在实现机制、执行效率、锁粒度和业务影响方面存在显著差异。从MySQL 8.0.12开始,对于任何支持的DDL操作,默认算法为INSTANT。MySQL会自动选择当前操作所支持的最高效算法,优先级为:INSTANT > INPLACE > COPY,也可通过ALGORITHM=子句显式指定。

1.1 COPY算法

COPY算法是最传统的DDL执行方式,在Server层完成表结构变更。其核心流程如下:

  1. 加锁阶段:DDL执行即刻获取表级排他MDL锁,此时所有针对该表的查询、写入操作全部挂起等待。
  2. 创建临时表:按照新的表结构创建一张临时表(.frm +表空间文件)
  3. 全量拷贝数据:逐行从原表读取数据,插入到临时表中
  4. 记录增量变更:DDL执行期间原表的DML操作会被阻塞
  5. 切换表文件:删除原表,将临时表重命名为原表名
  6. 重建索引:所有索引随数据拷贝一并重建
  7. 释放锁:元数据切换完成后释放排他锁,业务读写恢复正常。

COPY算法全程在Server层执行,需要调用引擎层接口逐行读写,过程中产生大量redo/undo日志,磁盘IO和CPU开销极高。

COPY算法是MySQL最原始的DDL实现方式,优点是兼容性最高、支持所有表结构变更;缺点是对业务影响极大,大表执行期间会导致长时间的业务中断,生产环境应尽量通过合理的表设计避免触发COPY算法。

1.2 INPLACE算法

INPLACE算法在InnoDB引擎层内部完成变更,避免了Server层逐行拷贝的开销。根据是否需要重建数据/索引,分为No-Build(仅元数据变更)和Build(数据/索引重建)两条执行路径,全程仅在提交阶段短暂持有排他锁。

1)准备阶段(Prepare)

  • 持有共享MDL锁,允许并发读
  • 创建临时索引文件/临时数据文件
  • 分配Row Log缓冲区记录DDL期间的增量变更

2)执行阶段(Execute)

  • 释放排他锁,允许并发DML读写
  • 扫描原表数据,按新结构构建数据页或索引页
  • 期间产生的DML增量写入Row Log缓冲区

3)提交阶段(Commit)

  • 升级为排他MDL锁,短暂阻塞DML
  • 应用Row Log中的增量变更到新结构
  • 更新数据字典,切换表空间文件
  • 清理临时文件

INPLACE并非完全"不产生临时文件",而是在引擎层内部完成数据重组,避免了Server层的逐行拷贝开销。对于仅修改元数据的操作(如删除索引),则无需扫描数据。

1)No-Build模式(无重建)

  • 仅修改InnoDB数据字典中的元数据定义,不扫描、不修改任何物理数据页
  • 无Row Log缓冲区开销,执行速度快,通常秒级内完成
  • 典型场景:删除普通索引、修改字段默认值、同字节区VARCHAR扩容

2)Build模式(重建型)

  • 需要全量扫描原表数据,按目标结构重新构建数据页或索引页
  • 执行期间通过Row Log缓冲区记录并发DML的增量变更,提交阶段统一回放应用
  • 耗时与数据量正相关,但全程仅提交阶段短暂锁表
  • 典型场景:新增普通索引、调整主键、表碎片整理、非末尾新增字段
1.3 INSTANT算法

INSTANT是MySQL 8.0.12引入的最轻量级DDL算法,仅修改数据字典中的元数据,完全不操作实际数据页,通过元数据版本机制实现读写兼容,执行耗时与数据量无关。

  1. InnoDB为每张表维护元数据版本号,DDL仅递增版本号并更新结构定义,不操作磁盘数据
  2. 执行INSTANT DDL时,仅更新数据字典中的表结构定义(列信息、默认值、注释等)
  3. 数据页本身不做任何修改,旧数据行按旧格式存储
  4. 后续读取数据时,InnoDB根据数据字典的最新定义解析行数据。新增列时读取旧行时自动填充默认值(NULL或常量默认值);删除列时读取时跳过已删除列的字段偏移。
  5. 后续写入新数据时,按最新表结构写入完整行格式

INSTANT算法的本质是"元数据先行,数据懒更新"。物理数据页的格式统一会在后续DML更新或OPTIMIZE TABLE时逐步完成。

1.4 三种算法业务影响对比

下图以时间轴横向推进的方式对比COPY、INPLACE、INSTANT三种算法在完整执行周期内的锁状态变化,以及对业务DML读写的阻塞窗口。

1)COPY算法:全程排他锁

  • 锁持有周期:DDL语句执行开始即获取排他MDL锁,直到整个表拷贝、切换完成后才释放。
  • 业务影响:
    • 阻塞窗口 = 整个DDL执行时长,与数据量线性相关,大表可达数小时。
    • 期间所有针对该表的SELECT/INSERT/UPDATE/DELETE全部挂起,连接堆积,严重时引发服务雪崩。
    • 典型场景:跨越字节边界的VARCHAR扩容、修改字段类型、变更字符集等。

2)INPLACE算法:两短一长,仅提交瞬间阻塞

  • 准备阶段(毫秒级):持有可升级共享MDL锁,允许并发DML读写,仅阻塞其他DDL操作;主要工作是创建临时文件、分配Row Log缓冲区。
  • 执行阶段(分钟~小时级):
    • 维持共享锁,完全允许并发DML,业务读写正常。
    • 后台扫描数据构建新结构,同时通过Row Log记录期间的增量变更。
    • 对业务的影响仅体现为磁盘IO升高、性能轻微下降,无阻塞。
  • 提交阶段(毫秒~秒级):
    • 升级为排他MDL锁,短暂阻塞所有DML。
    • 回放Row Log增量、切换表空间、更新数据字典、清理临时文件。
    • 这是INPLACE唯一的业务阻塞窗口。
  • 隐藏风险:若表上存在长事务未提交(持有共享MDL锁),提交阶段的排他锁请求会进入等待队列,进而阻塞后续所有DML,形成MDL锁队列雪崩。

3)INSTANT算法:毫秒级锁,业务无感知

  • 锁持有周期:仅在更新数据字典的瞬间持有排他MDL锁,耗时通常 < 10ms,之后立即释放。
  • 业务影响:
    • 阻塞时间极短,正常业务完全无感知,不会造成连接堆积。
    • 无数据扫描、无IO压力,对性能无影响。
  • 注意:若表上存在运行中的长事务,INSTANT DDL同样会等待MDL锁,但等待的是事务结束,而非DDL本身执行慢。

4)以下是三种算法业务影响对比

1.5 常见DDL操作默认算法及时长
1.5.1 常见DDL操作默认算法

基于MySQL 8.0.25版本,以下列出各常见DDL场景的默认执行算法。如在末尾新增单个字段、修改字段默认值等都是默认INSTANT算法;AFTER语法新增字段、删除字段使用INPLACE(Rebuild)算法;修改字段类型、表字符集转换等使用COPY算法。

关于VARCHAR长度边界的补充说明。VARCHAR扩展规则核心是"长度前缀字节数是否变化":063用1字节、6465535用2字节,同区间内扩展为Instant,跨区间为Copy;收缩VARCHAR长度同样需要Copy。VARCHAR 列的长度字节编码规则:

  • 0~255字节:使用1字节存储长度信息
  • ≥256字节:使用2字节存储长度信息

例如:

VARCHAR(10) → VARCHAR(50)(同属1字节区间):INPLACE,仅元数据 
VARCHAR(300) → VARCHAR(500)(同属2字节区间):INPLACE,仅元数据 
VARCHAR(50) → VARCHAR(100)(跨越1→2字节边界):COPY,全表重建

以上按单字节字符集计算。若使用utf8mb4,每个字符占4字节,则VARCHAR(63)为252字节(1字节长度),VARCHAR(64)为256字节(2字节长度),即63→64会跨越边界触发COPY。

1.5.2 常见DDL操作执行时长参考

以百GB级InnoDB表(千万行级数据量)为参考基准。使用INSTANT算法基本是在10ms内完成,持有MDL锁对业务影响也在这个时间范围;INPLACE算法的DDL执行时间与表数据量正相关,如添加普通索引,需要重新Build index,耗时在索引构造这个过程,数据量越大耗时越长,对业务的影响是在prepare和commit期间持有锁,耗时在秒级;COPY算法的DDL执行耗时也与表数据量相关,并且在执行过程中阻塞业务。因此对于使用到COPY算法执行的DDL语句,需评估好停业窗口,或者采用工具将非在线DDL转换为在线DDL(在线DDL工具pt-osc/gh-ost等)、大表的DDL使用分阶段数据迁移方案等。

1.6 DDL风险提示
  • NSTANT 64次限制:每个表最多执行64次INSTANT变更,达到限制后需执行OPTIMIZE TABLE或ALTER TABLE … ENGINE=InnoDB重建表重置计数器
  • INSTANT静默降级:即使指定ALGORITHM=INSTANT,在表包含BLOB类型、全文索引或使用特殊存储格式时,可能静默降级为INPLACE
  • MDL锁链式阻塞:DDL等待MDL写锁时,会阻塞后续所有对该表的请求,可能导致连接池打满
  • 高写入表:Inplace期间并发DML写入row_log,超过innodb_online_alter_log_max_size(默认 128MB)将导致DDL失败回滚。
  • 磁盘空间校验:Rebuild和COPY类DDL会生成完整的临时表空间,大表操作前必须确认磁盘剩余空间 ≥ 原表大小的1.2倍,避免空间占满引发故障。

参考资文档:

  1. MySQL 8.0 Official Documentation: 17.12.1 Online DDL OperationsMySQL
  2. MySQL 8.0 Official Documentation: 17.12.2 Online DDL Performance and ConcurrencyMySQL
  3. MySQL Blog: MySQL 8.0 INSTANT ADD and DROP Column(s)MySQL

我觉得可以把 INSTANT 当成“低成本操作”,但不能当成“零成本操作”。尤其是频繁改表结构的团队,最好还是把字段设计、发布流程、回滚预案都管起来。

1 个赞

回答“INSTANT 能不能随便做”:不能太飘。INSTANT 很快,但不代表没风险,长事务照样能卡 MDL,而且次数限制、特殊字段类型、版本差异都要看。生产上该评估还是要评估。

3 个赞

我的经验是上线前先查长事务:information_schema.innodb_trx、processlist 都扫一遍。DDL 执行时设好 lock_wait_timeout,不要让它无限等,不然很容易把小问题拖成事故。

3 个赞

从学术一点的角度说,原生 Online DDL 和外部在线变更工具解决的是不同层面的并发控制问题。前者依赖引擎内部机制,后者通过增量同步和最终切换降低阻塞窗口。高风险场景下,外部工具提供了更强的运维可控性。

3 个赞

说实话,很多团队设计表的时候不会想到这么细,直到第一次 ALTER 卡住才开始补课。这个点挺适合写进数据库变更规范里。

3 个赞

我会分级处理:小表直接 ALTER,中等表看业务低峰,大表必须走工具或影子表迁移。DBA 最怕的不是 DDL 慢,是它慢的时候你还没法优雅收手。

2 个赞

这就是 MySQL 的“冷知识伤人”系列。VARCHAR(63) 看着和 VARCHAR(64) 差不多,落到 utf8mb4 可能就是两个世界。

2 个赞

回答“原生 Online DDL 还是 pt-osc/gh-ost”:我一般先看操作类型。如果 EXPLAIN 或文档确认是 INSTANT,那原生就够了;如果会走 INPLACE Rebuild,也要看表大小和写入量;一旦可能 COPY,我基本不会直接在生产跑,宁愿上 gh-ost 或迁移方案。

1 个赞