MySQL 在线 DDL 怎样规划索引变更窗口
MySQL 的在线 DDL 不是“执行期间完全没有影响”。以 InnoDB 二级索引为例,创建索引通常可以在表继续读写时进行,但初始化和收尾仍可能等待元数据锁,在线变更还会消耗临时空间并记录并发 DML。规划窗口时,核心不是找一个“绝对安全”的时间,而是先锁定算法与并发级别,再把等待、磁盘和长事务列入退出条件。
官方地址:https://dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl-performance.html
对普通二级索引,先在测试环境确认 ALGORITHM=INPLACE, LOCK=NONE 可用;生产窗口只在长事务较少、临时空间充足、能观察元数据锁的时段执行。若声明的算法或锁级别不被当前操作支持,应让语句失败并重新评估,而不是接受未知的降级路径。
1. 先判断这次索引变更会走哪条路径
索引操作要先看对象和存储引擎。MySQL 8.4 文档把“添加二级索引”列为可 INPLACE、可并发 DML、但不是只改元数据的操作;删除或重命名普通索引的资源特征又不同。不要因为都写成 ALTER TABLE 就把它们当成同一种变更。
| 操作 | 常见形态 | 窗口关注点 |
|---|---|---|
| 添加普通二级索引 | INPLACE,通常允许 DML | 构建时长、磁盘、在线变更日志、收尾锁 |
| 删除普通索引 | INPLACE,通常允许 DML | 确认没有业务查询仍依赖该索引 |
| 添加 FULLTEXT 或 SPATIAL 索引 | 限制更多 | 不要套用普通二级索引的 LOCK=NONE 预期 |
| 主键或表结构重建 | 可能需要更重的路径 | 单独评估,不与本篇的普通二级索引窗口混用 |
如果目标是普通二级索引,可以先用明确参数试运行一条最小变更语句。参数不兼容时让 MySQL 报错,比让默认策略替你选择一个未知路径更容易复盘。
2. 用 ALGORITHM 和 LOCK 把窗口边界写进语句
ALGORITHM 描述执行算法,LOCK 描述并发访问限制。对需要保持业务读写的普通二级索引,常见起点如下;它表达的是“若不能满足这两个条件就失败”,不是对所有表都适用的保证。
-- 只对目标表添加普通二级索引,并拒绝不满足预期的路径 ALTER TABLE orders ADD INDEX idx_orders_customer_created (customer_id, created_at), ALGORITHM=INPLACE, LOCK=NONE; -- 执行前先记录当前连接和表名,便于把等待定位到同一变更 SELECT CONNECTION_ID() AS connection_id, DATABASE() AS database_name; -- 仅查看元数据锁等待,不把这条查询当作线上验证替代品 SELECT OBJECT_SCHEMA, OBJECT_NAME, LOCK_TYPE, LOCK_STATUS FROM performance_schema.metadata_locks WHERE OBJECT_NAME = 'orders';

LOCK=NONE 允许并发查询和 DML,但语句仍可能在开始或结束阶段等待短暂的排他元数据锁。LOCK=SHARED 会阻塞 DML,LOCK=EXCLUSIVE 则会阻塞查询和 DML。窗口规划时应把锁级别当作业务可接受的停顿上限,而不是只看 ALTER 主体是否“在线”。
3. 把长事务、磁盘和在线日志放进窗口设计
真正容易被忽略的是变更周边的资源。创建二级索引时,MySQL 需要临时排序文件和在线变更日志;并发 DML 很重时,在线日志可能增长到上限。另一方面,一个迟迟不提交的事务可能让 DDL 在最终切换处等待,即使主体阶段一直允许业务写入。
-- 观察 InnoDB 事务年龄,优先处理明显拖尾的长事务 SELECT trx_id, trx_started, trx_mysql_thread_id, trx_query FROM information_schema.innodb_trx ORDER BY trx_started; -- 执行前确认临时目录和数据目录仍有可用空间 SHOW VARIABLES LIKE 'tmpdir'; SHOW VARIABLES LIKE 'innodb_tmpdir'; -- 记录在线变更日志上限,避免只盯着 ALTER 的会话输出 SHOW VARIABLES LIKE 'innodb_online_alter_log_max_size';

这几项不是要求你提前猜出完成时间,而是帮助定义停止条件:磁盘逼近安全线、在线日志持续增长、元数据锁等待超过业务容忍值,或长事务无法解释时,暂停新增变更并保留现场信息。索引 DDL 不能像普通事务那样靠 ROLLBACK 还原已完成的结构变化,所谓回滚预案通常是停止本次操作、保留旧索引并另行设计反向 DDL。
4. 用一张执行清单决定是否进入窗口
- 变更对象确认:表是 InnoDB,索引是普通二级索引,列顺序和命名已评审。
- 算法确认:用
ALGORITHM=INPLACE和LOCK=NONE表达最低可接受条件。 - 业务确认:窗口内没有批量导入、归档、重试风暴或大量长事务。
- 资源确认:数据目录、
tmpdir、innodb_tmpdir和在线日志上限有余量。 - 退出确认:明确谁观察元数据锁、谁记录错误、何时停止后续变更。
- 结果确认:完成后再检查索引定义和执行计划,不把“命令返回成功”当成查询收益证明。
对于一次只添加普通二级索引的变更,适合把“语句失败”作为安全边界,把“等待超过阈值”作为窗口退出信号,把“索引是否改善目标查询”作为后续独立评估。这样做比单纯安排一个凌晨时间更可靠。
常见问题
在线 DDL 为什么还会卡住?主体阶段可以并发 DML,但开始或结束阶段仍需要元数据锁;长事务或其他 DDL 会让这一步等待。
为什么不直接省略 ALGORITHM 和 LOCK?默认策略会尽量选择可行路径,但显式写出最低接受条件能让不兼容场景直接失败,减少窗口内的意外降级。
添加索引失败后能不能 ROLLBACK?不要把 ALTER 当成业务事务设计。应根据错误保留现场、停止后续变更,并按当前索引状态设计下一次操作。
MySQL optimizer_trace 查看范围优化决策路径的配置方法
- 上一篇
- MySQL optimizer_trace 查看范围优化决策路径的配置方法
- 下一篇
- MySQL JSON_MERGE_PATCH 怎样按对象字段合并文档
-
- 数据库 · MySQL | 1小时前 |
- MySQL sys schema 怎样查看表空间使用率
- 122浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL 事务隔离级别怎样缩小锁等待范围
- 400浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL JSON_MERGE_PATCH 怎样按对象字段合并文档
- 267浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL optimizer_trace 查看范围优化决策路径的配置方法
- 128浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL 大 IN 列表怎样理解索引估算成本
- 244浏览 收藏
-
- 数据库 · MySQL | 1小时前 | 执行计划 · Mysql索引 · mysql 不可见索引 optimizer_switch FORCE INDEX USE INDEX
- MySQL 不可见索引被 USE INDEX 指定时为什么报错
- 304浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL JSON_PRETTY 怎样把 JSON 文档格式化输出
- 395浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL GET DIAGNOSTICS 怎样读取存储程序的错误信息
- 318浏览 收藏
-
- 数据库 · MySQL | 1天前 | mysql explain partition pruning 分区裁剪 partitions
- MySQL 怎样从执行计划判断分区裁剪
- 464浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL INSERT IGNORE 怎样识别被忽略的行
- 448浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL histogram 怎样更新列分布统计而不改表结构
- 386浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL LAG 怎样比较相邻日期记录
- 166浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 548次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 601次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 628次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 581次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 405次使用
-
- MySQL 明明加了索引,为什么查询还是很慢?先查这 6 个点
- 2026-06-27 374浏览
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- golang 基于 mysql 简单实现分布式读写锁
- 2023-01-07 384浏览
-
- 详解如何利用GORM实现MySQL事务
- 2023-01-07 184浏览
-
- Go语言实现操作MySQL的基础知识总结
- 2023-01-23 265浏览

