mysql 8.0不可见索引用于灰度验证,使优化器忽略索引但维持其存在与约束;不替代蓝绿发布,主键不可设为不可见,切换可见性需原子操作且支持秒级回退。

MySQL 8.0 的不可见索引不是蓝绿发布工具,但能支撑灰度验证环节——它让你在不删索引的前提下,让优化器“假装看不见”,从而安全评估索引变更影响。
不可见索引不能替代蓝绿发布,但能做索引层的灰度验证
蓝绿发布本质是两套环境切换流量,而 MySQL 单实例无法靠不可见索引实现服务级隔离。不可见索引只作用于查询优化器决策,对 DML(INSERT/UPDATE/DELETE)无影响:索引仍被维护、仍占用空间、仍受唯一性约束检查。它解决的是“这个索引到底有没有用”的验证问题,不是“新旧逻辑并行运行”。
- 主键和隐式主键(如 NOT NULL + UNIQUE 组合)不能设为不可见,否则报错
ER_PRIMARY_CANT_BE_INVISIBLE - 不可见索引对
EXPLAIN不出现,但SHOW INDEX和INFORMATION_SCHEMA.STATISTICS仍可见 - 如果业务 SQL 显式用了
USE INDEX(i_idx)提示,而该索引已设为INVISIBLE,会直接报错ER_KEY_DOES_NOT_EXITS
创建不可见索引的三种写法及适用场景
新建索引时就设为不可见,是最推荐的灰度起点——避免上线即生效带来的风险。
- 建表时定义:
CREATE TABLE t1 (i INT, j INT, INDEX i_idx (i) INVISIBLE) ENGINE=InnoDB;——适合新表或重构表结构 - 单独建索引:
CREATE INDEX j_idx ON t1 (j) INVISIBLE;——适合已有表快速加索引做验证 - 改表加索引:
ALTER TABLE t1 ADD INDEX k_idx (k) INVISIBLE;——语义清晰,兼容性好
注意:INVISIBLE 是关键字,不能加引号;大小写不敏感,但建议全大写保持可读性。
如何安全地从不可见切到可见(灰度发布关键动作)
确认监控指标(QPS、慢查数、执行计划稳定性)无异常后,再开放索引给优化器使用。这步必须原子执行,且建议在低峰期操作。
- 切换命令只有这一种:
ALTER TABLE t1 ALTER INDEX i_idx VISIBLE; - 切换后立即用
EXPLAIN SELECT * FROM t1 WHERE i = 1;验证是否命中,别只信SHOW INDEX的Visible: YES - 切可见后若发现性能回退,可秒级回切:
ALTER TABLE t1 ALTER INDEX i_idx INVISIBLE;,无需重建索引 - 切可见不锁表(Online DDL),但会触发一次元数据锁等待,确保没有长事务阻塞
容易被忽略的两个硬限制
这两个点线上踩坑率高,文档里常被轻描淡写:
-
optimizer_switch系统变量默认关闭use_invisible_indexes,所以你不用显式关它——但如果你在测试环境手动开过,上线前务必检查生产库是否也开了,否则不可见索引会被误用 - 不可见索引仍参与唯一性校验:比如
UNIQUE INDEX u_idx (email) INVISIBLE,插入重复email仍会报ER_DUP_ENTRY,这点和“完全删除”有本质区别
真正平滑的索引演进,靠的不是一次切换,而是“建不可见 → 观察一周 → 切可见 → 再观察三天 → 删旧索引”这样的节奏。不可见索引只是中间那根保险绳,扯断它之前,得先看清下面有没有坑。











