DROP分区后全局索引变UNUSABLE是Oracle强制一致性保护机制,因B-tree无法局部验证被删分区条目,故立即置为UNUSABLE且不报错;修复须先ALTER INDEX ... UNUSABLE再REBUILD,UPDATE GLOBAL INDEXES仅对后续DDL有效。
drop 分区后全局索引变 unusable,不是操作失败,而是 oracle 的强制一致性保护机制——必须手动重建,加 update global indexes 只对“未来”的 ddl 有效,对已发生的失效完全无效。
为什么 DROP PARTITION 后索引立刻变成 UNUSABLE
Oracle 不会自动清理全局索引中指向被删分区的条目,因为跨分区索引结构(B-tree)无法局部验证有效性。它选择“宁可停用,也不返回错误结果”,所以执行完 ALTER TABLE ... DROP PARTITION,索引状态就从 VALID 变成 UNUSABLE,且不报错、不写日志,极易被忽略。
- 本地索引(
LOCAL)不受影响:每个分区索引段独立,删分区等于删掉对应索引段 - 全局索引(
GLOBAL)必须全量扫描修正,Oracle 默认不干这事,除非你明确告诉它要干(即加UPDATE GLOBAL INDEXES) - 哪怕只删一个空分区,只要没带该子句,索引照样变
UNUSABLE
如何确认当前哪些全局索引已失效
别猜,直接查数据字典。失效的索引不会在 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通常表示函数索引依赖失效,和分区无关,不用管 - 如果表是分区表,还要查
user_ind_partitions确认局部索引分区状态,但全局索引没有分区视图,只看user_indexes就够
修复已失效的全局索引:UNUSABLE + REBUILD 是最稳组合
直接 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 - 切勿用
UPDATE INDEXES补救:它只是 DDL 选项,不是修复命令,对已失效索引完全无作用
下次做 DROP PARTITION 时怎么避免重蹈覆辙
加 UPDATE GLOBAL INDEXES 是预防手段,但不是万能的:
- 它只适用于
DROP/EXCHANGE/SPLIT/MERGE,不支持TRUNCATE PARTITION - 代价真实:实测可能比不加慢 3–10 倍,且需要额外 1.2–1.5 倍临时空间
- 锁行为是
SRX(Share Row eXclusive),会阻塞 INSERT/UPDATE,但不影响 SELECT - 超大表(TB 级)+ 高频写入场景下,更推荐“先置 UNUSABLE 再异步重建”,而非硬扛
UPDATE GLOBAL INDEXES
真正容易被忽略的是:失效索引不会主动告警,也不会在 DDL 执行后提示。等业务 SQL 报 ORA-01502 时,往往已经过去几小时甚至几天——查状态这一步,永远要放在分区操作之后、上线之前。











