当SYS和SYSTEM用户中出现重复数据库对象的时候会对数据库的使用带来很多的问题。系统一旦使用到这些重复对象的时候将会报错。
什么情况下会出现这种重复现象呢?
一般情况下SYS和SYSTEM用户下的数据库对象都是在数据库安装的过程中完成的。不过个别情况下为了部署新特性需要手工执行创建脚本。一般规律是这样的:但凡涉及到手工操作的部分,就潜在出错因素,一旦可能出错,便一定会出错。这便是“墨菲定律”。
本文给出这类故障的模拟和处理方法。
1.确认系统SYS和SYSTEM用户中是否存在重复数据库对象
sys@ora10g> show user
USER is "SYS"
sys@ora10g> select object_name, object_type from dba_objects where (object_name,object_type) in (select object_name,object_type from dba_objects where wner = 'SYS') and wner = 'SYSTEM';
OBJECT_NAME OBJECT_TYPE
AQ$_SCHEDULES TABLE
AQ$_SCHEDULES_PRIMARY INDEX
DBMS_REPCAT_AUTH PACKAGE
DBMS_REPCAT_AUTH PACKAGE BODY
注意,以上四条重复信息是正常现象,不要人为删除。
除此之外的信息需要考虑清理。
2.模拟误操作导致生成重复数据库对象
$ORACLE_HOME/rdbms/admin目录下的大部分手机号码脚本都应该在SYS用户下执行,如果手工在SYSTEM用户下执行后便会出现重复问题。
我们选取其中一个脚本sql.bsq在SYSTEM用户下执行。
system@ora10g> show user
USER is "SYSTEM"
system@ora10g> @sql.bsq
……省略执行输出……
sys@ora10g> select object_name, object_type from dba_objects where (object_name,object_type) in (select object_name,object_type from dba_objects where wner = 'SYS') and wner = 'SYSTEM';
OBJECT_NAME OBJECT_TYPE
AQ$_SCHEDULES TABLE
AQ$_SCHEDULES_PRIMARY INDEX
DBMS_REPCAT_AUTH PACKAGE
DBMS_REPCAT_AUTH PACKAGE BODY
I_INDSUBPART_POBJSUBPART$ INDEX
I_INDSUBPART_OBJ$ INDEX
INDCOMPART$ TABLE
I_INDCOMPART_BOPART$ INDEX
I_INDCOMPART$ INDEX
……省略部分输出信息……
C_COBJ# CLUSTER
I_COBJ# INDEX
CCOL$ TABLE
I_ICOL1 INDEX
I_CCOL1 INDEX
I_CCOL2 INDEX
TSQ$ TABLE
SUPEROBJ$ TABLE
I_SUPEROBJ1 INDEX
I_SUPEROBJ2 INDEX
IDL_UB1$ TABLE
IDL_CHAR$ TABLE
122 rows selected.
可见此时在SYSTEM用户下出现了很多重复的数据库对象。
3.批量删除重复的数据库对象
可以使用SQL脚本生成批量伤处重复对象的脚本。
sys@ora10g> select 'DROP ' || object_type || ' SYSTEM.' || object_name || ';' "Generate Drop Scrips" from dba_objects where object_name||object_type in (select object_name||object_type from dba_objects where wner = 'SYS') and wner = 'SYSTEM';
Generate Drop Scrips
DROP TABLE SYSTEM.AQ$_SCHEDULES;
DROP INDEX SYSTEM.AQ$_SCHEDULES_PRIMARY;
DROP PACKAGE SYSTEM.DBMS_REPCAT_AUTH;
DROP PACKAGE BODY SYSTEM.DBMS_REPCAT_AUTH;
DROP INDEX SYSTEM.I_INDSUBPART_POBJSUBPART$;
DROP INDEX SYSTEM.I_INDSUBPART_OBJ$;
DROP TABLE SYSTEM.INDCOMPART$;
DROP INDEX SYSTEM.I_INDCOMPART_BOPART$;
DROP INDEX SYSTEM.I_INDCOMPART$;
DROP TABLE SYSTEM.PARTLOB$;
……省略部分输出信息……
DROP CLUSTER SYSTEM.C_COBJ#;
DROP INDEX SYSTEM.I_COBJ#;
DROP TABLE SYSTEM.CCOL$;
DROP INDEX SYSTEM.I_ICOL1;
DROP INDEX SYSTEM.I_CCOL1;
DROP INDEX SYSTEM.I_CCOL2;
DROP TABLE SYSTEM.TSQ$;
DROP TABLE SYSTEM.SUPEROBJ$;
DROP INDEX SYSTEM.I_SUPEROBJ1;
DROP INDEX SYSTEM.I_SUPEROBJ2;
DROP TABLE SYSTEM.IDL_UB1$;
DROP TABLE SYSTEM.IDL_CHAR$;
122 rows selected.
删除脚本已经生成完毕。
批量执行这些脚本即可,注意最前面的四个数据库对象不要删除。
在删除的过程也许会遇到很多ORA错误,根据具体提示进行处理即可。确保清理的完整性。
4.重复数据清理效果确认
sys@ora10g> select object_name, object_type from dba_objects where (object_name,object_type) in (select object_name,object_type from dba_objects where wner = 'SYS') and wner = 'SYSTEM';
OBJECT_NAME OBJECT_TYPE
AQ$_SCHEDULES TABLE
AQ$_SCHEDULES_PRIMARY INDEX
DBMS_REPCAT_AUTH PACKAGE
DBMS_REPCAT_AUTH PACKAGE BODY
OK,重复数据库对象清理完毕。
5.小结
这里提醒各位DBA朋友的是:
1)对生产系统进行升级和手工操作之前尽量做好有效备份;
2)执行手工维护前一定要确保执行的当前用户是否正确;
3)出现问题后不要急于处理,做好缜密分析;
4)处理过程中尽量选择批量的方法以便节省时间。
本文提到的方法同样适用于多个普通用户间出现重复数据库对象的场景。
Good luck.
secooler
11.04.26
-- The End --