暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一次数据字典更改引发的隐患

华创信科 2017-07-20
187


 

      Oracle数据字典是由oracle来自动管理的,不需要我们人为干预,但是有很多人自做聪明,去更改oracle数据字典,这个是我2006年在客户那里遇到的一个由于数据字典更改引起的严重后果

 

问题描述:

客户反应进行数据库割接的时候,使用rman备份出来的数据,在其他主机进行恢复,数据库不能打开。425日,下午,察看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# 82110的不存在,说明数据字典不一致。

 

查看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

发现数据文件11082的表空间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用户的数据。到此问题已经清楚了。

 

问题处理

由于当时oracleoracle 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错误,使得数据库不能打开。

 

最终结局:

    客户是比较幸运的,如果他们的存储瘫痪,进行数据库恢复是无法恢复的也就是他们的备份集是没有用的,因此,建议大家定期在其他机器进行恢复实验。


文章转载自华创信科,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论