ORACLE 11G中,当表无数据时,不分配segment,以节省空间。详情请看其他文档,在笔者的环境中,分配表空间的参数已修改,非分区表的空表也可以导出。
问题:
在导出时报错EXP-00003: 未找到段 (0,0) 的存储定义。经过检查,发现报错的表都是分区表,且并非所有分区表都报错。于是拿正常导出的分区表与报错的分区表对比,发现索引部分有区别。
有问题的表索引:
正常的表索引:
原因:
Oracle数据库中,有两种类型的分区索引,全局索引和本地索引。
在使用全局索引时,假如表中新加了分区,不会在全局索引中自动增加新的分区,必须手工添加相应的分区。且对表分区进行DROP、TRUNCATE或者移动表空间等操作,会导致全局索引失效。
而使用本地索引时,如果新建分区,系统会自动以和表分区相同的名字自动创建一个索引分区。删除表分区时,相对应的索引分区也自动被删除,不会影响其他分区。
关于全局索引与分区索引的应用场景,本文不作赘述,此处引用大佬的文章:
http://blog.itpub.net/12679300/viewspace-2134128
目前看来,该报错是因为分区表的全局索引失效。
验证:
建立全局索引,查看索引表:
select INDEX_NAME,TABLE_NAME,STATUS from user_indexes;
目前索引状态是可用的;
DROP掉一个分区:
alter table audit_balance_df drop partition F_00000000;
再次查看索引表:
状态变为不可用。
建立本地索引,查看索引分区表:
select index_name,partition_name,status from user_ind_partitions;
本地索引状态为可用;
DROP掉一个分区:
alter table audit_balance_fz drop partition F_00000000;
再次查看索引分区表:
该索引分区随着表分区的删除而被删除,但没有影响其他分区,其他分区仍可用。
解决
方法一:
若的确需要使用全局索引,则在每次进行drop、truncate或move操作后重建索引:
alter index index_name(实际索引名) rebuild;
或批量执行:
select 'alter index '||index_name||' rebuild;' from user_indexes;
复制执行结果并运行,重建所有索引。
方法二:
若的确需要使用全局索引,则在每次进行drop、truncate或move操作时加上update indexes参数;
alter table audit_balance_DF DROP partition F_00000000 update indexes;
方法三:
将全局索引修改为本地索引。
drop index AUDIT_BALANCE_DF1;-- 删除全局索引
create index AUDIT_BALANCE_DF1 on AUDIT_BALANCE_DF (BOOKCODE, BSUBJCODE)
nologging local;-- 新建本地索引
结果:
经检查,库中的非前缀索引应用不多,且产品部门需给出标准库和清库脚本,每次重建容易出错,故本次操作采用方法三,将全部分区表的索引都修改为本地索引。
修改完成后重新执行exp、imp操作,没有报错。运行清库脚本后再次进行导出导入操作,仍无报错。至此问题解决。
相关引用:
https://www.linuxidc.com/Linux/2018-02/150984.htm – 分区索引失效原因
https://zhuanlan.zhihu.com/p/64694560 --关于局部前缀索引和非前缀索引
https://blog.csdn.net/cltt980248285/article/details/100443690
–同文中提到的关于全局索引与分区索引的应用场景
https://fzy15116089232.blog.csdn.net/article/details/10609401
–ORACLE 索引的三种状态: VALID、 N/A 、UNUSABLE