欢迎光临
我们一直在努力

数据库无损变更 Online DDL 深度原理解析

前言

在早期的MySQL中,我们每个Alter语句、建删索引都是全程阻塞的。

那么在变更期间我们会加上MDL排他锁(DML会自动获取MDL共享锁),业务的 INSERT、UPDATE、DELETE 甚至 SELECT 都无法执行。为了不影响业务,DBA 只能在凌晨 2 点爬起来执行变更。

为了解决这个痛点,Online DDL(在线表结构变更) 应运而生。它允许在执行 DDL 的同时,不阻塞 DML(增删改查)操作,真正实现了“边变更边服务”。

一、DDL算法演进

1.1 MySQL 5.5 及之前的 COPY 算法

在这个阶段,DDL 的执行极其粗暴:

  • 锁住原表(禁止写入)。

  • 创建一个结构改变后的临时表。

  • 将原表数据逐行拷贝到临时表中。

  • 重命名临时表替换原表。

  • 释放锁。
    痛点:全程锁表,数据量越大,业务宕机时间越长。

  • 1.2 MySQL 5.6 ~ 5.7 的 INPLACE 算法

    MySQL 5.6 引入了真正意义上的 Online DDL。它在 InnoDB 引擎层直接修改数据,避免了 Server 层面的数据拷贝,并且引入了 Row Log(行日志) 机制,使得变更期间允许并发 DML。

    1.3 现代:MySQL 8.0 的 INSTANT 算法

    MySQL 8.0 祭出了大杀器 —— 秒级加列(INSTANT DDL)。
    它巧妙地绕过了修改数据文件的过程,只修改数据字典(元数据)。无论表里有 100 行还是 10 亿行数据,加字段的操作都能在毫秒级瞬间完成。

    二、原生 Online DDL 底层原理

    很多开发者认为 INPLACE 就是不产生临时文件,其实这是一个误区。我们以 MySQL 5.6+ 的 INPLACE 算法为例,深度拆解 Online DDL 的生命周期。

    Online DDL 通常分为三个阶段:

    阶段一:Initialization(初始化阶段)

    • 数据库会评估这条 DDL 能够使用哪种算法(INSTANT > INPLACE > COPY)。

    • 注意:此时需要获取表的 MDL(Metadata Lock,元数据锁)的排他锁。虽然时间极短,但如果此时有慢查询正在占用该表,DDL 会被阻塞,进而阻塞后续所有的读写请求!

    阶段二:Execution(执行阶段)

    这是耗时最长的阶段,但它不阻塞业务 DML:

  • 降级锁:将 MDL 排他锁降级为共享锁,允许业务继续对表进行增删改查(DML)。

  • 构建数据:根据新表结构读取原表数据,在底层重新构建 B+ 树(对于加索引或重建表的操作)。

  • 记录 Row Log:在这个漫长的重建过程中,业务产生的新 INSERT/UPDATE/DELETE 操作会被记录到一个特殊的缓存中,称为 Row Log(在线日志)。

  • 阶段三:Commit(提交阶段)

  • 升级锁:再次短暂获取 MDL 排他锁(阻塞极短时间的写入)。

  • 应用 Row Log:将阶段二中记录的 Row Log 回放(Apply)到新的表结构中,追平数据差异。

  • 替换并清理:更新数据字典,完成新旧交替。

  • 核心逻辑总结:Online DDL 的精髓在于 “基线数据迁移 + 增量日志追平” 的思想。


    总结

    总结:如何选择与实战建议

    一表看懂三者的区别:

    算法特性 COPY (拷贝) INPLACE (原地) INSTANT (即时)
    MySQL版本 5.5及之前 5.6 引入 8.0 引入
    执行速度 极慢(随数据量递增) 慢(随数据量递增) 极快(毫秒级,与数据量无关)
    阻塞业务写入? 全程阻塞 (锁表) 仅首尾极短时间阻塞 仅首尾极短时间阻塞
    需要双倍磁盘? 是 (如果是重建表)
    修改了数据文件? 是 / 否 绝对不修改 (只改元数据)
    典型场景 极少数特殊变更 建索引、优化表、改数据类型 加字段、删字段、改表名
    赞(0)
    未经允许不得转载:171主机测评 » 数据库无损变更 Online DDL 深度原理解析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址