MySQL 8.0 Invisible Index与降级索引:零风险索引变更操作指南

索引变更的风险与Invisible Index的原理

在线上MySQL环境中添加或删除索引是高风险操作。添加索引期间,MySQL需要全表扫描构建索引数据,大表的ALTER操作可能持续数小时甚至数天,期间持有MDL锁阻塞DML操作。删除索引更危险——如果查询依赖该索引,删除后可能导致全表扫描,瞬间拖垮数据库性能。

MySQL 8.0引入的Invisible Index(不可见索引)解决了这个问题。不可见索引对优化器不可见,但引擎层面仍然维护——INSERT/UPDATE/DELETE操作依然会更新不可见索引,只是SELECT查询不会使用它。这相当于一个安全的软删除机制,可以在不影响查询的情况下验证索引是否真的不需要。

Invisible Index的基本操作

-- 创建不可见索引
ALTER TABLE orders ADD INDEX idx_status_created (status, created_at) INVISIBLE;

-- 将现有索引设为不可见
ALTER TABLE orders ALTER INDEX idx_status_created INVISIBLE;

-- 恢复索引可见性
ALTER TABLE orders ALTER INDEX idx_status_created VISIBLE;

-- 查看索引可见性
SELECT index_name, is_visible
FROM information_schema.statistics
WHERE table_schema = 'mydb' AND table_name = 'orders';

安全删除索引的完整流程

Step 1:将目标索引设为不可见

ALTER TABLE orders ALTER INDEX idx_old_index INVISIBLE;

Step 2:观察期(建议至少7天)

观察期内监控慢查询日志和性能指标,确认没有查询因索引不可见而退化为全表扫描。关键监控项:

-- 检查是否有全表扫描查询
SELECT * FROM sys.schema_unused_indexes
WHERE object_schema = 'mydb';

-- 查看慢查询是否增加
SELECT * FROM mysql.slow_log
WHERE start_time > NOW() - INTERVAL 1 HOUR
ORDER BY query_time DESC LIMIT 10;

Step 3:确认安全后删除索引

ALTER TABLE orders DROP INDEX idx_old_index;

Step 4(如果发现问题):快速恢复

ALTER TABLE orders ALTER INDEX idx_old_index VISIBLE;

恢复操作是元数据级别的,瞬间完成,不需要重建索引数据。

安全添加索引的流程

添加索引同样可以用Invisible Index做预验证:

-- Step 1:创建不可见索引
ALTER TABLE orders ADD INDEX idx_new_cover (user_id, status, created_at) INVISIBLE;

-- Step 2:强制优化器使用不可见索引进行测试
SET SESSION optimizer_switch = 'use_invisible_indexes=on';
EXPLAIN SELECT user_id, status, created_at FROM orders WHERE user_id = 1001;

-- Step 3:验证执行计划正确后,设为可见
SET SESSION optimizer_switch = 'use_invisible_indexes=off';
ALTER TABLE orders ALTER INDEX idx_new_cover VISIBLE;

use_invisible_indexes=on是Session级别参数,只影响当前连接,其他会话不受影响。这样可以在生产环境中安全地测试新索引的效果。

Online DDL配合Invisible Index的最佳实践

对于大表添加索引,MySQL 8.0的Online DDL可以在不锁表的情况下完成:

ALTER TABLE large_table 
  ADD INDEX idx_new (column_a, column_b) INVISIBLE,
  ALGORITHM=INPLACE,
  LOCK=NONE;

ALGORITHM=INPLACE表示在原表上操作,不拷贝全表数据;LOCK=NONE允许并发DML。但需要注意:

1. Online DDL期间仍然需要短暂的MDL锁(开始和结束阶段),如果此时有长事务持有MDL锁,DDL会等待。

2. Inplace方式创建索引需要额外的临时空间,大约是索引大小的1-2倍。

3. 对于超大表(数十亿行),考虑使用pt-online-schema-change或gh-ost工具,它们通过创建影子表加增量同步的方式实现零锁表变更。

降级索引与索引合并策略

当索引策略需要调整但不希望完全删除旧索引时,降级索引是一个折中方案——将旧索引设为不可见,创建新索引替代。如果新索引效果不理想,旧索引可以秒级恢复:

-- 降级旧索引
ALTER TABLE orders ALTER INDEX idx_old_composite INVISIBLE;

-- 创建新索引
ALTER TABLE orders ADD INDEX idx_new_composite (col_a, col_b, col_c) VISIBLE;

-- 如果新索引有问题,快速回滚
ALTER TABLE orders ALTER INDEX idx_old_composite VISIBLE;
ALTER TABLE orders DROP INDEX idx_new_composite;

Invisible Index是MySQL 8.0给DBA最重要的安全工具之一。结合use_invisible_indexes的Session级测试和Online DDL,索引变更的风险可以降到极低。核心原则:先不可见再删除,先不可见测试再可见上线。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/mysql80invisibleindex-yu-jiang-ji-suo-yin-ling-feng-xian/

(0)
小编小编
上一篇 15小时前
下一篇 15小时前

相关推荐