エクスポート(Oracle11gR2)での注意点(0件のテーブル)

ITコーディネータのシュウです。

DSC_2897

ラグビーワールドカップで、日本がサモアを破り、2勝目をあげました。ほぼ完ぺきなかたちでサモアの攻撃を抑えて、前半は何と20-0、後半もサモアの攻撃を1トライに抑えての完勝といっていい内容でしたね。見ていてとても興奮しました。次のアメリカ戦も是非頑張ってほしいと思います。

さて、dbSheetClientには、EXCEL版だけでなく、Access版というものもありますが、この夏Access版の体験版がリリースされています。Access版については、「仙ちゃんのシステムフォロー記」という記事でも詳しく説明がありますので、是非興味のある方はそちらを読んでみてください。こちらもExcel版と同様、データベースにはOracle、SQL Serverなどを利用してシステムを構築できます。
http://www.newcom07.jp/dbsheetclient/access/forrow6.html

 <本日の題材>
エクスポート(Oracle11gR2)での注意点(0件のテーブル)

最近、Oracle11gR2にて、テスト環境の作成のため、スキーマごとエクスポート(expコマンド)して、テスト用ユーザにインポート(impコマンド)したときに、一部のテーブルが作成されず、それを使用したプロシージャがコンパイルされないということを経験しました。
よくよく調べてみると、インポート(impコマンド)が失敗しているという訳ではなく、エクスポート(expコマンド)の際に、全てのテーブルがエクスポートされていなかったのです。どういうテーブルがエクスポートされなかったかというと、データ件数が0件のテーブルです。
何故こういうことが起きるのか、原因を調べていくと、Oracle11gR2のデータベース・ユーティリティについてのドキュメントに、以下のような記載がありました。

オリジナルのエクスポート
・Oracle Database 11gリリース2(11.2)では、デフォルトで、DEFERRED_SEGMENT_CREATIONパラメータがTRUEに設定されます。つまり、作成した表は、データの最初の行が表に挿入されるまでセグメントがありません。オリジナルのエクスポートではセグメントのない表が無視されます。したがって新しい表を作成しても、エクスポートの前にデータを挿入しないと、それらの表はエクスポートされません。(データ・ポンプ・エクスポートではこの制限がありません。これはセグメントのない表が無視されないためです。)
http://docs.oracle.com/cd/E16338_01/server.112/b56303/whatsnew.htm

 つまり、作成した表に1行でも行を登録しないとセグメントが作成されず、そのためもともとのexportコマンドでは無視されてしまうということです。
昔から利用していた exportコマンドではなく、データ・ポンプ・エクスポートと言われる expdpコマンドでのエクスポートでは、こういうことは起きないということなので、こういうケースの対応としては、以下のどれかになると思われます。

・expdpコマンドでのエクスポート、及びimpdpコマンドでのデータ・ポンプ・インポートを行う。
・初期化パラメータ「DEFERRED_SEGMENT_CREATION」パラメータを「FALSE」に変更して、exportコマンドを実行する。
・件数が0件というテーブルをなくしてから、エクスポートを行う。

しかし、3番目は現実的には難しいと思われるので、1番目か2番目の対応となりますよね。

実際に試してみます。

例)
SCOTTユーザのスキーマに、以前ブログの自律型トランザクションの題目でも紹介したエラーのログをためるための「ERROR_LOG」テーブルを作成し、それを利用するプロシージャ「RECORD_ERROR」を作成した直後に、通常のexportを実施します。

このとき、scottのスキーマにあるテーブルには何があるか確認します。
SELECT TABLE_NAME FROM USER_TABLES;

scott_table

ここで、scottユーザのスキーマごとexportを実行します。
exp scott/tiger file=scott.dmp  STATISTICS=none

exsport_scott

(※STAISTICS=none は、「EXP-00091: 不審な統計をエクスポートしています。」のエラーが出ないようにするためのもので、統計情報をエクスポートしない設定に今回はしています)

エクスポートされているテーブルに、先ほど作成したデータが0件の「ERROR_LOG」テーブルがないことがわかります。こうなると、このダンプファイルをインポートしても「ERROR_LOG」テーブルは存在しないので、それを使っているプロシージャはエラーになってしまいます。

次に、expdpコマンドによるデータ・ポンプ・エクスポートを実行してみます。

まず、前段階として、ディレクトリの作成とread/write権限の付与を行います。

sqlplus / as sysdba
create or replace directory DP_DIR as ‘\work\dpdir’;
grant read, write on directory DP_DIR to SCOTT;

directory

その後、expdpコマンドで、SCOTTユーザのスキーマ全体をバックアップします。

expdp scott/tiger directory=DP_DIR dumpfile=scott.dmp

expdp_scott

先ほどのexportではエクスポートされなかった0行の「ERROR_LOG」テーブルが、今回はエクスポートされているのが確認できます。

このエクスポートファイルを、scott2 というスキーマに丸ごとインポートします。

impdp dbadmin/パスワード directory=DP_DIR dumpfile=scott.dmp REMAP_SCHEMA=scott:scott2

impdp_scott

※以前のimpコマンドでは、FROMUSER=scott  TOUSER=scott2 となっていたところが、impdpコマンドでは、REMAP_SCHEMA=scott:scott2 となります。

上記によってインポートされたscott2ユーザのほうでは、「ERROR_LOG」テーブルもインポートされ、それを使ったプロシージャもVALID(使用可能)な状態となっています。

さて、もう一つの初期化パラメータ「DEFERRED_SEGMENT_CREATION」パラメータを「FALSE」に変更して、exportコマンドを実行するほうも試してみます。

sysdbaでログインし、初期化パラメータ「DEFERRED_SEGMENT_CREATION」を確認した後、FALSEに変更します。

sqlplus / as sysdba
SHOW PARAMETER DEFERRED_SEGMENT_CREATION
ALTER SYSTEM SET DEFERRED_SEGMENT_CREATION=FALSE;

alter_system_def

この状態で、再度、exportコマンドを実行してみます。

exsport_scott_after

しかし、今回も「ERROR_LOG」テーブルはエクスポートされませんでした。

ここで、初期化パラメータを変更した後に、データが0件の「ERROR_LOG」テーブルを再作成する必要があるようです。

一旦DROP TABLEを行った後に、再度 CREATE TABLEを行います。(プロシージャも再度コンパイルします)
その後、もう一度exportを実行してみます。

 exsport_scott_after2

 今度は、「ERROR_LOG」テーブルがエクスポートされているのが確認できました。少し手間な部分もありますが。。。

今日は以上まで

 

にほんブログ村 IT技術ブログへ
にほんブログ村