DROP PARTITION 后全局索引变 UNUSABLE 是 Oracle 的强制一致性保护机制,修复须先 ALTER INDEX ... UNUSABLE 再 REBUILD;跳过第一步或误用 REBUILD PARTITION 均失败。

直接结论:DROP PARTITION 后全局索引变 UNUSABLE 不是故障,是 Oracle 的强制一致性保护机制;修复必须分两步——先 ALTER INDEX idx_name UNUSABLE,再 ALTER INDEX idx_name REBUILD。跳过第一步或试图用 REBUILD PARTITION 会失败。
为什么 DROP PARTITION 后全局索引立刻变成 UNUSABLE
Oracle 不会自动清理全局索引中指向被删分区的 B-tree 条目,因为跨分区结构无法局部验证有效性。它选择“宁可停用,也不返回错误结果”,所以 ALTER TABLE ... DROP PARTITION 执行完,user_indexes.status 就从 VALID 变成 UNUSABLE,且不报错、不写日志——极易被忽略。
本地索引(LOCAL)不受影响:每个分区索引段独立,删分区等于删掉对应索引段;但全局索引(GLOBAL)必须全量扫描修正,Oracle 默认不干这事,除非你明确加 UPDATE GLOBAL INDEXES。
- 哪怕只删一个空分区,只要没带
UPDATE GLOBAL INDEXES,索引照样变UNUSABLE -
UPDATE GLOBAL INDEXES是 DDL 选项,不是修复命令,对已发生的失效完全无效 - 常见误判:看到
EXPLAIN PLAN没走索引,或SELECT报ORA-01502,才去查状态——其实该在每次 DROP 后立刻查
怎么确认哪些全局索引已经失效
别猜,直接查数据字典。全局索引没有分区视图,只看 user_indexes 就够:
SELECT index_name, status, funcidx_status FROM user_indexes WHERE table_name = 'YOUR_TABLE' AND index_type = 'NORMAL';
看到 status = 'UNUSABLE' 就是它了。funcidx_status = 'DISABLED' 通常表示函数索引依赖失效,和分区无关,不用管。
- 如果表有主键或唯一约束,注意检查以
pk_或uk_开头的索引——它们常是全局唯一索引,最容易因 DROP 分区失效 - 不要只查
user_ind_partitions:全局索引没有分区,查这个视图会返回空 - 状态为
VALID不代表能用:某些版本下status字段更新延迟,建议配合SELECT COUNT(*) FROM your_table WHERE rownum = 1实测是否报ORA-01502
修复 UNUSABLE 全局索引的正确步骤
直接 ALTER INDEX ... REBUILD 有风险:若索引当前是 VALID,重建全程锁索引;若已是 UNUSABLE,某些 Oracle 版本会拒绝执行并报 ORA-01408(误导性错误)。正确做法是两步显式控制:
- 先快速置为不可用:
ALTER INDEX idx_name UNUSABLE—— 这步毫秒级,几乎不阻塞 DML - 再重建:
ALTER INDEX idx_name REBUILD TABLESPACE ts_name PARALLEL 4—— 指定表空间和并行度可提速 - 如需归档安全,加
LOGGING:REBUILD LOGGING PARALLEL 4 - 线上业务敏感?加
ONLINE:REBUILD ONLINE可减少锁表时间,但不能消除阻塞
切勿用 UPDATE INDEXES 补救:它只是 DDL 选项,不是修复命令,对已失效索引完全无作用。
ALTER INDEX REBUILD PARTITION 报 ORA-14086 怎么办
这个错误不是语法写错,而是你在对一个整体已 UNUSABLE 的本地索引强行操作单个分区。Oracle 明确禁止:只要 user_indexes.status 是 UNUSABLE,REBUILD PARTITION 就不接受。
先跑 ALTER INDEX idx_name REBUILD —— 这会重建全部分区,把索引拉回 VALID 状态。重建完立刻查 user_ind_partitions.status,如果还有个别分区仍是 UNUSABLE(极少见,多见于中断后残留),再针对性执行 ALTER INDEX idx_name REBUILD PARTITION p_name。
容易被忽略的一点:全局索引没有 REBUILD PARTITION 语法,这个命令只对本地索引有效;对全局索引执行会直接报错,而不是静默忽略。


















