Oracle数据字典是由oracle来自动管理的,不需要我们人为干预,但是有很多人自做聪明,去更改oracle数据字典,这个是我2006年在客户那里遇到的一个由于数据字典更改引起的严重后果
问题描述:
客户反应进行数据库割接的时候,使用rman备份出来的数据,在其他主机进行恢复,数据库不能打开。4月25日,下午,察看xx客户原有数据库,发现问题及现象。
诊断过程:
查看数据库的alert日志发现:
Fri Apr 21 23:46:21 2006
Dictionary check beginning--- 检查数据字典
Fri Apr 21 23:46:21 2006
Errors infile/oracle/app/admin/lfjf/udump/ora_9176_jf1.trc:
ORA-00600: internal error code,arguments:[12620], [82], [4294967295], [], [], [], [], []
Fri Apr 21 23:46:24 2006
Errors in file/oracle/app/admin/lfjf/udump/ora_9176_jf1.trc:
ORA-00600: internal error code,arguments:[12620], [82], [4294967295], [], [], [], [], []
Error 600 happened during db open,shuttingdown database
USER: terminating instance due to error 600
Instance terminated by USER, pid = 9176
最初我没有往数据字典考虑,先去查询support.oracle.com(当时是support.metalink.com),没有发现此ora-600[12620]错误,也就是oracle没有这方面的问题出现过,后来客户说我们有三个数据文件是recover状态,我才开始检查数据库的信息,和alert中的详细信息,确实可能一句话就起到很大作用。大家看上面数据库在Dictionarycheck beginning后就出现了问题。因此,检查数据字典看数据库是否一致。
Errors infile/oracle/app/admin/lfjf/udump/ora_9176_jf1.trc:
ORA-27302: failure occurred at: skgpwreset1
ORA-27303: additional information:invalidshared ctx
ORA-01092: ORACLE instance terminated.Disconnectionforced
ORA-00600: internal error code, arguments:[12620],[82], [4294967295], [], [], [], [], []
Fri Apr 21 23:59:41 2006
Starting ORACLE instance (normal)
察看udump下的ora_9176_jf1.trc文件:
ksedmp: internal or fatal error
ORA-00600: internal error code,arguments:[12620], [82], [4294967295], [], [], [], [], []
Current SQL statement for this session:
alter database open
----- Call Stack Trace -----
calling call entry argument values in hex
location type point (? means dubious value)
------------------------------------------------ ----------------------------
ksedmp()+236 ? ksedst() 800000010006ABC0 ?
400000000025BB98 ?
5555555555555555 ?
100010000 ?
ksfdmp()+24 ? ksedmp() 800003FFBFFF95F8 ?
C0000000168F62D8 ?
800000010007C3C0 ?
4000000000F20D63 ?
kgeriv()+152 ? ksfdmp() 800000010007C3C0 ?
4000000000F20D63?
0FFFFFFFF?
475F494E44585F31 ?
kgesiv()+124 ? kgeriv() 475F494E44585F31
-----
kwqjw *kwqjwh_p [80000001000D8CA8,80000001000D8CB0) = 00000000 00000000
knceug *kncem_p [80000001000D8CB0,80000001000D8CB8) = 00000000 00000000
ub1 kkziu_p[80000001000D8CB8,80000001000D8CC0) = 09000000
hogxdef*hogcu_p [80000001000D8CC0,80000001000D8CC8) = 00000000 00000000
ub4 ksmugmg2[80000001000D8CC8,80000001000D8CD0) = 0000CDCD
ORA-00600:internal error code, arguments:[12620], [82], [4294967295], [], [], [], [], []
ORA-27302:failure occurred at: skgpwreset1
ORA-27303:additional information: invalidshared ctx
ORA-01092:ORACLE instance terminated. Disconnectionforced
ORA-00600:internal error code, arguments:[12620], [82], [4294967295], [], [], [], [], []
检查数据库数据文件为recover状态的:
SQL>select name,status from v$datafilewhere status='RECOVER';
Name status
_______________________ ________
/dev/vgjf2/rlg2_d21_p2_dat2 RECOVER
/dev/vgjf2/rlg2_d15_p2_dat9 RECOVER
/dev/vgjf5/rlg5_d59_1G_dat04 RECOVER
…….
察看数据文件所属表空间:
SQL>select file#,ts# from v$datafilewhere file# in(82,110,229);
File# ts#
________ _____
82 26
110 29
229 47
查看dba_data_files:
SQL>select file_id,file_name fromdba_data_files where file_id in(82,110,229);
229 dev/vgjf5/rlg5_d59_1G_dat04
只有一个数据文件,发现file# 为82,110的不存在,说明数据字典不一致。
查看dba_data_files视图所在的基表:
SQL>selecta.file#,a.ts# from file$ a,v$datafile bwhere a.file#=b.file# andb.status='RECOVER';
82
110
229 47
发现数据文件110,82的表空间ts#为空,说明数据库的基表被人更改过。
查看数据文件为recover状态的是否有数据:
SQL> select segment_name fromdba_extentswhere file_id=82;
no rows selected
SQL> c/82/110
1*select segment_name from dba_extents where file_id=110
SQL> /
no rows selected
SQL> c/110/229
1*select segment_name from dba_extents where file_id=229
SQL> /
no rows selected
发现三个数据文件都没有内容;
然后查看表空间的数据:
SQL> select file#,ts# from v$datafilewherefile# in(82,110,229);
82 26
110 29
229 47
SQL> select name from v$tablespace where ts# in(26,29,47);
ACCT_DATA_1_AREA1
ACCT_DATA_2_AREA1
BILLING_INDX_1_AREA3
SQL>select segment_name fromdba_segments
where tablespace_name='BILLING_INDX_1_AREA3';
no rows selected
发现表空间 BILLING_INDX_1_AREA3没有数据。但是另外两个表空间是bill用户的数据。到此问题已经清楚了。
问题处理:
由于当时oracle是oracle 816,在oracle 10g之前不支持删除数据文件,因此只能把这个表空间的数据迁移到新的表空间,处理步骤如下:
生成批量sql,来迁移数据
先处理表空间ACCT_DATA_1_AREA1
对于没有分区的表:
select ‘alter table ‘||owner||’.’||table_name||’ movetablespace 表空间名称;’ from dba_tables where tablespace_name=’ACCT_DATA_1_AREA1’ and PARTITIONED=’NO’
重新创建索引:
select ‘alter index ‘||owner||’.’||index_name||’ rebuildtablespace表空间名称;’ from dba_indexes where table_name in (select table_namefromdba_tables where tablespace_name=’ ACCT_DATA_1_AREA1’ andPARTITIONED=’NO’)
对分区的表需要分区单独去移到其他表空间
select 'alter table '||table_owner||’.’||table_name||'move partition '||PARTITION_NAME||'tablespace 表空间名称;’ fromdba_tab_partitions wheretablespace=’ACCT_DATA_1_AREA1’
重新创建索引:
SELECT 'alter index ' || index_owner|| '.'|| index_name || ' rebuild partition ' ||
partition_name || ' ;'
FROMdba_ind_partitions
WHERE status='UNUSABLE'
ORDERBY index_owner,index_name, partition_name;
处理表空间ACCT_DATA_2_AREA1
对于没有分区的表:
select ‘alter table ‘||owner||’.’||table_name||’ movetablespace 表空间名称;’ from dba_tables where tablespace_name=’ACCT_DATA_2_AREA1’ and PARTITIONED=’NO’
重新创建索引:
select ‘alter index ‘||owner||’.’||index_name||’ rebuildtablespace表空间名称;’ from dba_indexes where table_name in (select table_namefromdba_tables where tablespace_name=’ ACCT_DATA_2_AREA1’ andPARTITIONED=’NO’)
对分区的表需要分区单独去移到其他表空间
select 'alter table '||table_owner||’.’||table_name||'move partition '||PARTITION_NAME||'tablespace 表空间名称;’ fromdba_tab_partitions where tablespace=’ACCT_DATA_2_AREA1’
重新创建索引:
SELECT 'alter index ' || index_owner|| '.'|| index_name || ' rebuild partition ' ||
partition_name || ' ;'
FROMdba_ind_partitions
WHERE status='UNUSABLE'
ORDER BY index_owner,index_name,partition_name;
因为表空间BILLING_INDX_1_AREA3没有数据可以直接删除表空间。
删除有问题的表空间,但是当drop表空间的时候,一样报上边的ora-600错误,最终把ts#数据字典的file#更改回去,然后把对应的表空间删除,然后查看ts#没有问题。
总结原因:
因为现在数据库的基表已经不一致,因此,当用rman备份的时候。因为控制文件中记录的数据文件,表空间信息与数据库中的不一致,因此,可能产生备份的备份集有问题。使得备份集不可用。当进行全库恢复的时候使得打开数据库报ora-00600错误,使得数据库不能打开。
最终结局:
客户是比较幸运的,如果他们的存储瘫痪,进行数据库恢复是无法恢复的也就是他们的备份集是没有用的,因此,建议大家定期在其他机器进行恢复实验。