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 为什么卡住了,欢迎贴出来,我可以帮你分析!

相关推荐
程序新视界3 小时前
MySQL的联合索引以及其最左前缀原则
数据库·mysql
奥尔特星云大使3 小时前
mysql 全备+binlog恢复数据
数据库·mysql·adb·数据恢复·全量备份·binlog日志·二进制日志
the beard3 小时前
Redis Zset的底层秘密:跳表(Skip List)的精妙设计
数据库·redis·list
喂你撰写的故事4 小时前
timestamp存取差几小时? mysql timestamp的timezone问题以及如何在mysql2设置
mysql
William_cl4 小时前
【连载5】云数据库 MySQL 热点更新功能介绍
数据库·mysql
缘来如此095 小时前
mysql--核心日志文件详解
数据库·mysql
电商API_180079052475 小时前
电商数据分析之自动获取数据的技术手段分享
大数据·数据库·数据挖掘·数据分析
MilesShi5 小时前
RAG:解锁大语言模型新能力的关键钥匙
数据库·人工智能·语言模型
gsfl7 小时前
Redis 缓存
数据库·redis·缓存