是,MySQL 5.6前ADD INDEX会锁表;5.6起仅InnoDB表且无外键、无全文索引时,ADD非主键/非唯一索引才可能LOCK=NONE免锁。

ALTER TABLE ADD INDEX 会锁表吗
在 MySQL 5.6 之前,ALTER TABLE ADD INDEX 是典型的“全表拷贝”操作,会加写锁,阻塞所有 DML(INSERT/UPDATE/DELETE),业务高峰期直接雪崩。5.6 起引入 ALGORITHM=INPLACE 和 LOCK=NONE 控制能力,但不是所有情况都免锁。
- 只有
ADD INDEX(非主键、非唯一约束)且引擎是 InnoDB 时,才可能做到LOCK=NONE - 如果表上有外键、有全文索引、或 MySQL 版本
-
SHOW PROCESSLIST里看到altering table状态持续很久,大概率已在锁表
ONLINE DDL 的正确写法和参数含义
MySQL 5.6+ 必须显式指定 ALGORITHM 和 LOCK 才能控制行为,不写就按默认策略走,默认未必是在线的。
- 安全写法:
ALTER TABLE t1 ADD INDEX idx_col1 (col1) ALGORITHM=INPLACE, LOCK=NONE; -
ALGORITHM=INPLACE表示复用原表空间,不重建;ALGORITHM=COPY就是传统锁表模式 -
LOCK=NONE是目标,但 MySQL 会校验是否真能达成——若失败会报错ALGORITHM=INPLACE not supported,不会静默降级 - 执行前先查:
SELECT @@version;和SHOW CREATE TABLE t1;,确认无外键、无 FULLTEXT、引擎是 InnoDB
pt-online-schema-change 是更稳的选择吗
当不能确定是否满足 LOCK=NONE 条件,或 MySQL 版本低于 5.6,pt-online-schema-change(Percona Toolkit)是事实标准方案,它不依赖 MySQL 内置 DDL 机制,而是用触发器+影子表模拟在线变更。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 命令示例:
pt-online-schema-change --alter "ADD INDEX idx_col2 (col2)" D=test,t=t1 --execute - 它全程不锁原表,但会增加主从延迟、占用双倍磁盘空间、对写入吞吐有 10%~30% 影响
- 必须确保从库没延迟、binlog_format=ROW、原表有主键或唯一非空索引(否则触发器无法定位行)
- 别漏掉
--dry-run和--print先看计划,线上误操作代价很高
创建索引前必须检查的三件事
大表建索引不是“丢个语句就等结果”,失败往往发生在准备阶段。
- 查磁盘剩余空间:
df -h /var/lib/mysql——ALGORITHM=INPLACE也要临时排序缓冲,空间不足直接失败 - 确认查询模式:
EXPLAIN SELECT ... WHERE col1 = ?看是否真能命中新索引;盲目加索引反而拖慢写入 - 避开业务高峰:即使
LOCK=NONE,建索引过程仍会大量读取数据页、竞争 buffer pool,QPS 高时容易触发Waiting for table metadata lock
真正难的不是语法,是判断“此刻能不能建”——空间、负载、主从状态、索引有效性,缺一不可。漏查任意一项,都可能让一个 5 分钟的操作卡住 2 小时。










