HOME >> Tips >> Oracle

表領域のデータファイル縮小時にエラーが発生して失敗する

 
文書番号:20229




表領域のサイズを縮小しようとした際に「ORA-03297」エラーが発生し、縮小に失敗。。。


SQL>ALTER DATABASE DATAFILE 'データファイルのフルパス' RESIZE 変更後のサイズ;

行1でエラーが発生しました。:
ORA-03297:
ファイルには、リクエストしたRESIZE値を超える使用中のデータが含まれています。
使用量を見てサイズを指定しているのでおかしいと思って調べたところ、非常にわかりやすいサイトがありました。
http://d.hatena.ne.jp/bluerabbit/20100202/1265096263


10GBの表領域で1GBしか使用していないのにエラーが出た
これは、縮小可能なのはデータファイルの一番後ろにあるデータより後ろの部分だけだから。

概念としては

■□□□□■□□



■□□□□■

するだけ。

■■

このようにはならない。

■:使用済みデータブロック
□:未使用データブロック
いわゆるデフラグをするわけではなく、空き領域の後ろを切り捨てるだけなのでこうなるわけです。
これを縮小するにはデフラグ的なことを手動で実施する必要があります。

【実行手順】

  • まず表領域のエクステントを調べて末尾の方にあるオブジェクトを調べます。
    この結果はデータファイルの後ろから前へ順に取得できますので結果の上位から順に対応していくといいです。
    
    SELECT E.SEGMENT_NAME
          ,E.TABLESPACE_NAME
          ,E.EXTENT_ID
          ,E.BLOCK_ID
          ,E.BLOCKS
    FROM   DBA_EXTENTS E
    INNER JOIN DBA_DATA_FILES F
    ON E.FILE_ID = F.FILE_ID
    WHERE E.SEGMENT_TYPE = 'TABLE'
    AND   E.OWNER        = 'ユーザー名'
    AND   F.FILE_NAME    = 'データファイル'
    ORDER BY E.BLOCK_ID DESC;
    
  • まずはテーブルをSHRINK(圧縮)します。
    
    --行移動を有効にする
    ALTER TABLE テーブル名 ENABLE ROW MOVEMENT;
    
    --テーブルを圧縮する
    ALTER TABLE テーブル名 SHRINK SPACE CASCADE;
    
    --行移動を無効にする
    ALTER TABLE テーブル名 DISABLE ROW MOVEMENT;
    
  • これでもダメな場合は一時的に別の表領域へ移動して縮小後に戻します。
    
    ALTER TABLE テーブル名 MOVE TABLESPACE 表領域名;
    
  • 最終手段は一度エクスポートして表領域を作り直し、インポートします。
    ダウンタイムは長いですが確実に小さくできます。
    
    1.exp ユーザー/パスワード file=c:\aaa.dmp log=aaa.log
    
    2.表領域を削除する
    
    3.表領域を作成する
    
    4.imp ユーザー/パスワード file=c:\aaa.dmp log=aaa.log fromuser=ユーザー touser=ユーザー commit=y
    

【参考情報】

SQL*Plusコマンド・リファレンス
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19277-01/ch12.html