升级mysql 8.0后隐藏索引需主动启用,迁移后应先设为invisible验证影响:毫秒级生效、不影响写入,但需避开主键/唯一非空列;通过information_schema确认可见性、监控慢日志与performance_schema指标;注意force/use index等hint会绕过隐藏机制,须检查sql日志和optimizer_switch设置。

升级到 MySQL 8.0 后,隐藏索引不是“自动启用”的功能,它本身不参与迁移过程,但能极大降低迁移后索引策略调整的风险——关键在于你得在迁移完成、应用切流前,用它做真实负载下的索引影响验证。
迁移后怎么快速验证某个旧索引是否还能删?
别一上来就 DROP INDEX。先设为不可见,观察真实流量反应:
-
ALTER TABLE orders ALTER INDEX idx_legacy_status INVISIBLE;—— 毫秒级完成,不影响写入 - 必须确认该索引不是主键或第一个
UNIQUE NOT NULL列(否则报错ERROR 3522) - 查
INFORMATION_SCHEMA.STATISTICS确认IS_VISIBLE = 'NO',别只信SHOW INDEX的Visible字段(有延迟) - 重点盯:慢查询日志里原本走
idx_legacy_status的语句,Query_time是否跳升;performance_schema.table_io_waits_summary_by_index_usage中该索引的COUNT_STAR是否归零(注意:实例重启后清零,不能单凭这个下结论)
为什么 EXPLAIN 显示没走索引,但压测 QPS 还是掉?
因为隐藏索引照常消耗写入资源:INSERT/UPDATE/DELETE 仍要维护 B+ 树、校验唯一性、刷脏页。尤其当表有多个隐藏索引时,这种开销叠加明显:
- 检查
innodb_rows_inserted和innodb_buffer_pool_reads是否异常升高 - 对比迁移前后相同写入负载下的 CPU 使用率和磁盘 IO wait
- 如果发现写入变慢,问题很可能不在查询计划,而在这些“看不见却干活”的索引上
迁移测试中 FORCE INDEX 为什么还生效?
这是最常被忽略的失效点:FORCE INDEX、USE INDEX、IGNORE INDEX 这些提示不检查索引可见性,直接绕过优化器判断。一旦应用代码或 ORM 硬编码了这类 hint,隐藏索引就形同虚设:
- 执行
SELECT @@optimizer_switch LIKE '%use_invisible_indexes=on%';排查是否有人全局打开了开关 - 搜索应用 SQL 日志,看是否有
FORCE INDEX (idx_legacy_status)类语句 - 临时禁用 hint 影响的方法:在会话中加
SET SESSION optimizer_switch = 'use_invisible_indexes=off,use_index_extensions=on';,再跑 EXPLAIN
真正容易被绕过的不是语法或权限,而是那些写死在业务代码里的索引 hint 和全局开启的 use_invisible_indexes=on——它们会让整个测试失去意义。验证前,先扫一遍真实 SQL 流量和会话变量设置。











