無傷のデータを分離してORA-01410を取り除く方法

かつて、私はこのタスクに真剣に手を取りました-圧縮とOracleのバグの結果、いくつかのテーブルでいくつかの行が壊れました。 その結果、このようなテーブルにフルスキャンを使用しているユーザーはORA-01410を受け取りました。

最も困難なケースを検討してください-バックアップまたはインデックスがない場合(この場合、インデックス付きの列はインデックスによるスキャンで取得できます)。 この場合、唯一のオプションは、問題のあるROWIDを見つけ、それを2つの側面から「回避」して、無傷のデータを分離することです。



最初に、初期データを取得するために、問題のあるリクエストのトレースを削除します。

alter session set db_file_multiblock_read_count=1; alter session set events 'immediate trace name trace_buffer_on level 1048576'; alter session set events '10200 trace name context forever, level 1'; alter session set events '1410 trace name errorstack forever, level 10'; alter session set tracefile_identifier='ORA1410';
      
      







問題のリクエストを実行します

 select count(1) from test.testtable;
      
      





次のようなトレースでレコードを見つけます。

 ktrget2(): started for block <0x0645 : 0x3ce2c85b> objd: 0x00f842bb env: (scn: 0x0a21.9a61c1d8 xid: 0x0000.000.00000000 uba: 0x00000000.0000.00 statement num=0 parent xid: xid: 0x0000.000.00000000 scn: 0x0000.00000000 96sch: scn: 0x0000.00000000 mascn: (scn: 0x0a1f.ccec0b27) OBJD MISMATCH typ=6, seg.obj=16270011, diskobj=16268354, dsflg=100001, dsobj=16270011, tid=16270011, cls=1
      
      







受信した値に基づいて、Block_numberとRelative_fnoを取得します。

 select dbms_utility.data_block_address_file(to_number('3ce2c85b', 'xxxxxxxx')) file#, dbms_utility.data_block_address_block(to_number('3ce2c85b', 'xxxxxxxx')) block# from dual; FILE# BLOCK# 243 2279515
      
      







さらに、問題のオブジェクトのdata_object_idを見つけます。

 select data_object_id from dba_objects where owner = 'test' and object_name = 'testtable'; data_object_id ---------------------- 16402245
      
      







取得した値に基づいて、ROWIDを形成します。

 select dbms_rowid.rowid_create(rowid_type => 1,object_number => 16402245,relative_fno => 243,block_number => 2279515,row_number => 0) from dual; ROWID=AA+kdFADzAAIshbAAA
      
      





さて、実際には、冒頭で述べたこと-私たちはすべての側面から問題の行を回ります:

 insert into test.testtable_nocorrupt select /*parallel(8)*/ * from test.testtable where rowid<'AA+EK7ADzAAIshbAAA'; insert into test.testtable_nocorrupt select /*parallel(8)*/ * from test.testtable where rowid>='AA+EK7ADzAAIshcAAA';
      
      







このような問題は、db_block_checking / db_block_checksum = 'Full'またはdb_ultra_safe = 'data_and_index' DBパラメーターセットを設定することで回避される可能性が最も高いことに注意してください。信頼性が向上します。



Metalinkの使用メモ:

Oracle8以降でROWID範囲スキャンを使用して破損したテーブルからデータを抽出する[ID 61685.1]

OERR:ORA-8103「オブジェクトはもう存在しません」/トラブルシューティング、診断、およびソリューション[ID 8103.1]




All Articles