MySQL在线DDL:零停机改表实战指南

你提供的这段内容是 MySQL 官方文档的 17.12 节:InnoDB and Online DDL ,它详细介绍了 MySQL(尤其是 InnoDB)从 5.6 开始引入并持续优化的一项核心功能:在线 DDL(Online DDL)


🌟 一句话总结:

Online DDL 允许你在修改表结构(如加字段、建索引等)的同时,依然可以正常读写数据,几乎不影响业务运行。

这在现代高可用、高并发的生产环境中至关重要。


我们来逐段深入解读,并用通俗语言 + 实战建议帮助你理解。


🔹 17.12.1 Online DDL Operations(支持的在线 DDL 操作)

✅ 什么是 Online DDL?

传统的 ALTER TABLE 会锁表、复制整个表,耗时长、服务中断。而 Online DDL 改进了这一点:

  • Instant(瞬间完成):某些操作只需修改元数据,不碰数据文件。
  • In-Place(原地修改):不创建临时表,直接在原表上改,但仍需少量锁。
  • Copy(表复制):老方式,效率低,已尽量避免。

📊 不同操作类型对比(MySQL 8.0+)

操作 ALGORITHM 是否在线? 说明
ADD COLUMN(末尾) INSTANT(8.0.12+) ✅ 几乎无锁 只改元数据
ADD INDEX INPLACE ✅ 支持 DML 构建索引时允许读写
DROP INDEX INPLACE ✅ 完全在线 删除快
MODIFY COLUMN 类型变更 COPYINPLACE ❌/⚠️ 大部分需要复制表
ADD PRIMARY KEY INPLACE ✅ 但需排序 可能较慢
CHANGE COLUMN 名称或类型 多数 COPY 不推荐在线做

💡 提示:INSTANT 是 MySQL 8.0.12 的重大优化,比如加字段几乎"零延迟"。


🔹 17.12.2 Online DDL Performance and Concurrency(性能与并发控制)

⚙️ 你可以通过两个关键子句控制行为:

1. ALGORITHM={INSTANT \| INPLACE \| COPY}

  • 强制使用某种算法。
  • 用于调试或降级兼容。

2. LOCK={DEFAULT \| NONE \| SHARED \| EXCLUSIVE}

  • 控制 DDL 期间的并发级别。
LOCK 级别 允许 SELECT? 允许 DML(INSERT/UPDATE/DELETE)? 场景
LOCK=NONE 最宽松,适合高并发系统
LOCK=SHARED 只读可用,防写入
LOCK=DEFAULT 自动选择 自动选择 默认行为
LOCK=EXCLUSIVE 完全锁表,慎用

✅ 推荐做法:

sql 复制代码
ALTER TABLE users ADD COLUMN phone VARCHAR(20), 
    ALGORITHM=INPLACE, 
    LOCK=NONE;

这样如果无法做到"不锁",语句会立即失败,而不是卡住生产环境。


🔹 17.12.3 Online DDL Space Requirements(空间需求)

💾 空间消耗对比

算法 是否需要额外空间? 说明
ALGORITHM=INSTANT ❌ 几乎不需要 只改字典
ALGORITHM=INPLACE ⚠️ 少量 需要日志空间、排序缓冲等
ALGORITHM=COPY ✅ 需要 ≥ 2倍表大小 创建临时表 .tmp,风险高

📌 举例:一个 50GB 的表执行 ALGORITHM=COPY,需要至少 100GB 磁盘空间!

✅ 建议:

  • 监控磁盘空间。
  • 尽量避免 COPY 模式。

🔹 17.12.4 Online DDL Memory Management(内存管理)

  • Online DDL 在构建索引或重做表时会使用缓冲区。
  • 主要参数:
    • innodb_sort_buffer_size:排序用内存。
    • innodb_online_alter_log_size:记录 DDL 过程中 DML 变更的日志大小。

⚠️ 如果 DDL 期间有大量写入,这个日志可能溢出,导致失败。

✅ 建议:

  • 对大表 DDL,提前增大:

    sql 复制代码
    SET GLOBAL innodb_online_alter_log_size = 1073741824; -- 1GB

🔹 17.12.5 Configuring Parallel Threads for Online DDL(并行线程配置)

从 MySQL 8.0 起,某些 DDL 操作(如创建二级索引)可以并行执行,显著提升速度。

  • 使用参数:innodb_parallel_read_threads(默认 4)
  • 适用于:ADD INDEX 等 I/O 密集型操作。

✅ 示例:

sql 复制代码
-- 提高并行度
SET SESSION innodb_parallel_read_threads = 8;
ALTER TABLE orders ADD INDEX idx_user_id (user_id);

💡 类似于"多个人一起搬砖",加快索引构建。


🔹 17.12.6 Simplifying DDL Statements with Online DDL(简化 DDL 语句)

不需要每次都写 ALGORITHMLOCK,MySQL 默认会自动选择最优方式。

但你可以显式指定以确保安全:

sql 复制代码
-- 安全写法:必须在线,否则失败
ALTER TABLE logs ADD COLUMN status TINYINT,
    ALGORITHM=INPLACE,
    LOCK=NONE;

✅ 好处:防止意外锁表,适合自动化脚本。


🔹 17.12.7 Online DDL Failure Conditions(失败情况)

以下情况会导致 Online DDL 失败或退化为 COPY

  1. 使用了不支持 INPLACE 的操作(如改变列字符集)。
  2. 指定的 LOCK 级别无法满足(如要求 LOCK=NONE 但实际需要锁)。
  3. 磁盘空间不足。
  4. innodb_online_alter_log 溢出(DDL 期间写入太多)。
  5. 存在外键约束限制。

✅ 建议:在测试环境先试,查看 SHOW ENGINE INNODB STATUS 中的 DDL 日志。


🔹 17.12.8 Online DDL Limitations(限制)

当前仍有一些限制:

限制 说明
不支持 JSON 列的某些修改 如修改嵌套结构
分区表 DDL 更复杂 部分操作仍需锁表
ALTER TABLE ... RENAME COLUMN 8.0+ 支持,但底层可能是 COPY
外键约束可能阻止 LOCK=NONE 需注意依赖关系
ROW_FORMAT 修改可能触发复制 尤其是 COMPRESSED

✅ 实战建议(DBA 必看)

场景 推荐做法
加字段(末尾) MySQL 8.0.12+ 用 ADD COLUMN → 几乎无感
加索引 ALGORITHM=INPLACE, LOCK=NONE,避免高峰期
改字段类型 小心!可能触发 COPY,先评估
删除字段 支持 INPLACE,但建议先测试
生产环境 DDL 永远加上 LOCK=NONELOCK=SHARED,防止锁库
大表操作 提前调大 innodb_online_alter_log_size,开启并行

🧪 示例:安全地在线加字段和索引

sql 复制代码
-- 1. 加字段(MySQL 8.0.12+ 瞬间完成)
ALTER TABLE users 
    ADD COLUMN email VARCHAR(100) AFTER name,
    ALGORITHM=INSTANT,
    LOCK=NONE;

-- 2. 加索引(允许读写)
ALTER TABLE users 
    ADD INDEX idx_email (email),
    ALGORITHM=INPLACE,
    LOCK=NONE;

-- 3. 查看是否成功
SHOW PROCESSLIST; -- 观察是否有阻塞

📈 总结:Online DDL 的三大优势

优势 说明
高可用性 表不锁,服务不中断
节省空间 避免 COPY 模式占用双倍磁盘
提升效率 并行 + 快速算法(如 INSTANT)

🚨 最后提醒

不要以为所有 DDL 都是"在线"的!

一定要:

  1. 查看 MySQL 官方文档 确认操作是否支持 Online。
  2. 在测试环境验证。
  3. 生产环境使用 ALGORITHMLOCK 显式控制行为。

如果你有具体的 DDL 语句想知道是否"在线",或者想分析某个 DDL 为什么卡住了,欢迎贴出来,我可以帮你分析!

相关推荐
NineData4 小时前
NineData 迁移评估功能正式上线
数据库·dba
NineData10 小时前
数据库迁移总踩坑?用 NineData 迁移评估,提前识别所有兼容性风险
数据库·程序员·云计算
赵渝强老师12 小时前
【赵渝强老师】PostgreSQL中表的碎片
数据库·postgresql
全栈老石16 小时前
拆解低代码引擎核心:元数据驱动的"万能表"架构
数据库·低代码
倔强的石头_1 天前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
jiayou643 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
于眠牧北3 天前
MySQL的锁类型,表锁,行锁,MVCC中所使用的临键锁
mysql
李广坤4 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
Turnip12025 天前
深度解析:为什么简单的数据库"写操作"会在 MySQL 中卡住?
后端·mysql
爱可生开源社区5 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba