大表加索引危险在于同时冲击锁、性能、空间和稳定性四大维度:旧版MySQL全程锁表,新版仍可能触发MDL锁;建索引耗尽CPU与I/O,加剧主从延迟;磁盘占用翻倍易致失败;索引还可能因函数、类型转换或顺序错配而失效。

大表加索引之所以危险,核心在于它会同时冲击数据库的锁、性能、空间和稳定性四大关键维度,稍有不慎就可能引发线上故障。
锁表导致业务写入中断
MySQL 5.6 及更早版本中,ALTER TABLE ... ADD INDEX 采用 copy 算法,全程对表加写锁,期间所有 INSERT/UPDATE/DELETE 都会被阻塞。即使在 MySQL 5.7+ 支持 Online DDL,某些操作(如全文索引、主键变更)仍可能触发短暂但致命的元数据锁(MDL),尤其在高并发写场景下,容易堆积大量等待线程。
CPU 和 I/O 资源被彻底打满
创建索引需全表扫描并排序建树,过程消耗巨大:
- 单线程建索引时,CPU 利用率常飙至 90%+,拖慢其他查询响应
- 磁盘随机读 + 大量顺序写(索引页、redo log、binlog),I/O wait 暴涨
- 主从复制延迟可能激增——binlog 写入滞后,从库追不上主库节奏
磁盘空间突然告急
索引不是“轻量附加”,而是实实在在的额外存储:
- 普通二级索引体积约为原表数据的 20%–50%,千万级表轻松多占数 GB
- 建索引过程中,InnoDB 会先写临时索引文件,再原子替换,高峰期磁盘占用可达 原表 + 新索引 × 2
- 若空间不足,操作失败且回滚耗时极长(可能数十分钟),期间资源持续被占用
索引建了一半却失效或误用
即便成功加完索引,也不代表能用上:
- WHERE 条件对索引列用了函数(如
WHERE DATE(create_time) = '2025-01-01')、隐式类型转换(phone = 13800138000,而 phone 是 VARCHAR)都会让索引失效 - 联合索引顺序不匹配(如建了
(a,b,c)却只查WHERE b = ?),前面字段未参与,后面全作废 - 低选择性字段(如 status、gender)单独建索引,查询优化器大概率弃用,纯属浪费
不复杂但容易忽略:危险从来不是“能不能加”,而是“加得是否可控、可退、可验证”。










