alter table drop partition 使全局索引变 unusable 是因 oracle 主动停用索引防止悬空指针导致错误结果;本地索引不受影响,因其分区独立;exchange partition 等操作也需显式指定 update global indexes 或 including indexes 才能避免失效。

ALTER TABLE DROP PARTITION 为什么让全局索引变 UNUSABLE
Oracle 默认不自动清理全局索引中指向已删分区的条目——它不是“忘了维护”,而是主动停用整个索引,防止查询返回错误结果。只要 DROP PARTITION 没带 UPDATE GLOBAL INDEXES,执行完索引状态立刻变成 UNUSABLE,后续 INSERT 或 UPDATE 就会报 ORA-01502。
本地索引(LOCAL)不受影响:每个分区索引段独立存在,删分区等于删掉对应索引段,其余分区索引仍保持 USABLE。
-
DROP PARTITION只删表数据段,不碰索引结构 - 全局索引是跨分区的 B-tree,一条索引条目可能指向任意分区;删分区后,索引里残留大量“悬空指针”,Oracle 不敢假设一致性,直接置为不可用
- 这个过程静默发生,DDL 返回成功,但索引已失效——容易被忽略
EXCHANGE PARTITION 后索引失效的真正原因
执行 EXCHANGE PARTITION 时,如果没加 INCLUDING INDEXES(对本地索引)或 UPDATE GLOBAL INDEXES(对全局索引),索引就会失效。尤其注意:本地索引失效不是因为“没加子句”本身,而是元数据不一致触发的保护机制。
- 对
GLOBAL索引:必须显式写UPDATE GLOBAL INDEXES,否则等同于先删数据再不管索引 - 对
LOCAL索引:必须写INCLUDING INDEXES,否则 Oracle 认为新旧表索引结构不匹配,把整个索引置为UNUSABLE - 语法位置很关键:
UPDATE GLOBAL INDEXES必须紧接在主语句后、分号前,中间不能换行或加注释,否则 Oracle 直接忽略
已经 UNUSABLE 了,别急着 REBUILD
索引一旦变成 UNUSABLE,再补 UPDATE GLOBAL INDEXES 没用——它只对“尚未失效”的索引生效。此时得手动干预,但方式取决于索引类型和业务容忍度。
- 查状态优先:
SELECT index_name, status FROM user_indexes WHERE table_name = 'YOUR_TABLE',确认是否真为UNUSABLE - 全局索引重建耗时长、锁表久:
ALTER INDEX idx_name REBUILD会阻塞 DML,大表慎用;如需归档同步,记得加LOGGING - 本地索引可按分区重建:
ALTER INDEX idx_name REBUILD PARTITION p_name,影响范围小 - 若业务不能停,考虑
REBUILD ONLINE,但要注意:联机重建期间,该索引上的 DML 仍可能被延迟或阻塞
TRUNCATE PARTITION 为什么不能加 UPDATE GLOBAL INDEXES
TRUNCATE PARTITION 不支持 UPDATE GLOBAL INDEXES 子句,这是 Oracle 的硬性限制。它和 DROP PARTITION 不同:前者清空数据但保留分区结构,后者彻底删除分区定义。Oracle 认为 TRUNCATE 不改变分区边界,理论上不该影响全局索引,但实际中仍可能因内部元数据刷新延迟导致短暂不可用。
- 遇到
TRUNCATE PARTITION后索引异常,先查状态;若真为UNUSABLE,说明之前已有残留问题,不是本次操作直接导致 - 不要试图在
TRUNCATE语句后硬加UPDATE GLOBAL INDEXES,语法报错且无意义 - 真正要防的是
DROP/EXCHANGE/SPLIT这几类操作漏写维护子句——它们才是全局索引失效的主力场景
user_indexes.status,而不是凭 DDL 执行成功就认为万事大吉。











