Oracle中ALTER TABLE MOVE或SHRINK SPACE导致索引变为UNUSABLE,是因为行物理重排使ROWID全部变更,索引叶节点中旧ROWID失效,Oracle为保障一致性强制置为UNUSABLE,而非静默出错;两者影响逻辑一致,均需人工检查并重建索引。

Oracle表执行ALTER TABLE ... MOVE或SHRINK SPACE后,索引自动变为UNUSABLE,这不是bug,而是Oracle的强制一致性机制——因为ROWID变了,索引里存的旧物理地址就失效了。
为什么MOVE/SHRINK会导致索引不可用
表数据物理位置重排后,每行的ROWID必然改变。而B-tree索引叶节点里存储的是(key, ROWID)对,旧ROWID指向空块或错误位置,查询时无法定位真实数据行。Oracle为避免返回错误结果,直接将所有相关索引状态置为UNUSABLE,而不是静默出错。
-
ALTER TABLE t MOVE、ALTER TABLE t SHRINK SPACE、在线重定义(DBMS_REDEFINITION)都会触发该行为 - 分区表上执行
ALTER TABLE t MOVE PARTITION p1,只影响该分区对应的本地索引分区,全局索引全部失效 - 即使只移动一个分区,全局索引也必须重建或标记为
UNUSABLE,这是Oracle的原子性保障
SHRINK SPACE和MOVE对索引的影响有区别吗
没有本质区别。两者都重定位行数据,导致ROWID变更,索引失效逻辑完全一致。但注意:SHRINK SPACE要求表启用ENABLE ROW MOVEMENT,而MOVE不需要——但这不影响索引状态变化。
-
SHRINK SPACE是在线操作(可加COMPACT或CASCADE),但索引仍会变UNUSABLE -
MOVE是DDL独占锁操作,期间DML阻塞,但索引同样失效 - 两者都不会自动重建索引,也不会报错提示“索引已失效”,需人工检查
如何快速发现并修复失效索引
别等应用报ORA-01502才处理。应在收缩操作后立即验证索引状态,并按需重建。
- 查失效索引:
SELECT index_name, status FROM user_indexes WHERE status = 'UNUSABLE' - 查分区索引状态:
SELECT index_name, partition_name, status FROM user_ind_partitions WHERE status != 'USABLE' - 重建单个索引:
ALTER INDEX idx_name REBUILD ONLINE(推荐,不阻塞DML) - 重建分区索引:
ALTER INDEX idx_name REBUILD PARTITION p1 ONLINE - 跳过失效索引(仅临时应急):
ALTER SESSION SET SKIP_UNUSABLE_INDEXES = TRUE,但查询性能可能退化为全表扫描
容易被忽略的关键点
重建索引后,DEGREE(并行度)默认继承原值,如果原索引设过PARALLEL 4,重建后仍会触发并行执行,可能意外耗尽资源;另外,REBUILD ONLINE需要约1.5倍原索引大小的空闲空间,空间不足会失败,且中断后残留SYS_JOURNAL表需手动清理。


















