ORA-600 [12700] エラーでブロック破損とその対応

お仕事のDBサーバで Oracle 8i が見たことのないエラーを吐いて alert があがりました。ORA-600 [12700] というエラーです。アラートログには下記のようなエラーが出力されていました。

***
Corrupt block relative dba: 0x01c1b7fd file=7. blocknum=112637.
Fractured block found during buffer read
Data in bad block - type:6. format:2. rdba:0x01c1b7fd
last change scn:0x0000.02157a8e seq:0x1 flg:0x02
consistancy value in tail 0x37373737
check value in block header: 0x0, check value not calculated
spare1:0x0, spare2:0x0, spare2:0x0
Wed Mar 9 06:11:46 2005
Errors in file /db/SID/udump/ora_10597.trc:
ORA-00600: 内部エラー・コード,引数:[12700],[3559],[29406673],[84],[],[],[],[]

ちなみに、このエラーが出力されるとき Client 側から見たエラーは、
ORA-01578: ファイル番号 5,ブロック番号 64664でOracleデータ・ブロックに障害が発生しました。

のようになります。このエラーの意味は、ブロック障害が発生したという意味でかなり危険度が高い部類のエラーとなります。実際の復旧に関しては、ディスク上でブロックが実際に破損しているのか、ディスクからバッファへの読み込み時の問題で、バッファ上のみで破損しているのかで異なります。
- スポンサーリンク -


では、以下では ORA-600 [12700] / ORA-01578 の復旧手順について説明したいと思います。復旧は株式会社アシストの技術資料が参考になりました。
 

  • 障害の発生しているデータファイルの特定。
    上記のようなアラートログの赤色の部分の「fd file=7. blocknum=112637」に着目し、下記の SQL を実行する。
    select segment_type,owner||'.'||segment_name from dba_extents
    where file_id=7 and 112637 between block_id and block_id+blocks-1;
    得られる結果が、破損対象のデータファイル。
    SEGMENT_TYPE OWNER||'.'||SEGMENT_NAME
    ------------------ -------------------------
    TABLE SID.TABLE1
  • 次に analyze コマンドで整合性のチェックをします。
    analyze table SID.TABLE1 validate structure cascade;
    得られる結果が、破損対象のデータファイル。
    ERROR at line 1:
    ORA-01578: ORACLE data block corrupted (file # 5, block # 64664)
    ORA-01110: data file 5: '/db/SID/datafile1.dbf'
  • Oracle を停止してディスク上のブロック破損か、バッファ上のブロック破損かを特定。
    DB_VERIFY にて物理データファイルの整合性を確認します。
    dbv blocksize=8192 FILE=/db/SID/datafile1.dbf
    blocksizeの8192は、初期化パラメータdb_block_sizeで確認します。
    DB_VERIFYでは、その情報をチェックし、もし不整合が検出された場合には、その情報を出力します。
    エラーが出力されなかった場合、Oracle を再起動すれば復旧が完了します。エラーが発生している場合、コールドバックアップファイルとアーカイブログから完全復旧を行うか、破損ブロックを切り捨ててオンライン復旧をするかを選択します。
     
  • 復旧方法1:完全復旧
    コールドバックアップとその時点以降のアーカイブログが必要となります。復旧方法は一般的なので割愛します。
  • 復旧方法1:破損ブロックを切り捨ててオンライン復旧
    internal/oracle でログインして、event10231 を設定する。
    ALTER SESSION SET events '10231 trace name context forever,level 10'
    この状態で、問題の表から CREATE TABLE AS SELECT で、別の一時的な表にデータを保存します。
    CREATE TABLE SID.TABLE1_TMP AS SELECT * FROM SID.TABLE1;
    一時表に、破損ブロック以外のデータが保存されていますので、念のため内容を確認します。その後、問題の表を drop し一時表より再作成します。
    select * from SID.TABLE1_TMP;
    drop table SID.TABLE1;
    CREATE TABLE SID.TABLE1 AS SELECT * FROM SID.TABLE1_TMP;
    以上で無事に破損した部分以外のデータが復旧します。
 
ちなみに、当サイトでも業務支援ツールとして IT 企業からのダウンロードが非常に多い「Oracleアラートログの監視」で alert log をリアルタイム監視しているので、何か障害が発生したときには、いち早く対応ができて幸せになれます。Oracle を運用されている方は、かなり実績のあるツールなので、導入をおすすめ致します。
- スポンサーリンク -