RDS for Oracle 上のファイルの扱いについて
デーベースに限った話ではないですが、オンプレなのかマネージドサービスなのかの決定的な違いは、そのソフトウェアが稼働しているサーバーそのものに対する設定やファイルを自由に扱うことができない、という点だと思います。そのため管理コンソールから操作したり、専用のコマンドが用意されているわけです。アプリケーション開発者を含め、単純にデータベースを利用する立場であれば、さほど違いを感じないかもしれませんが、データベース管理者( DBA )ともなればそうはいきません。今回は、RDS for Oracle 上でのファイルの扱いについていくつか試してみたいと思います。
UTL_FILE パッケージでファイルを作成する
冒頭で書いたようにマネージドサービスの特徴は「サーバーそのものに対する設定やファイルを自由に扱えない」ことではありますが、決して「できない」と言ってるわけではありません。
まずは、RDS for Oracle に接続して、以下のような PL/SQL を実行します。
DECLARE
hndl UTL_FILE.FILE_TYPE;
BEGIN
hndl := UTL_FILE.FOPEN('DATA_PUMP_DIR','test.txt','w');
UTL_FILE.PUT_LINE(hndl,'This is a pen!');
UTL_FILE.PUT_LINE(hndl,'That is a notebook.');
UTL_FILE.FCLOSE(hndl);
END;
これでディレクトリ DATA_PUMP_DIR に “test.txt" ができており、その中身も以下のように参照できます。
SELECT * FROM TABLE(RDSADMIN.RDS_FILE_UTIL.READ_TEXT_FILE('DATA_PUMP_DIR','test.txt'));

作成したファイルも以下のように UTL_FILE.FREMOVE を使って削除できます。つまり、Oracle 経由であれば、比較的自由に色々できるということです。
EXEC UTL_FILE.FREMOVE('DATA_PUMP_DIR','test.txt');
DATA_PUMP_DIR の物理パスは?
言うまでもなく「DATA_PUMP_DIR」は Oracle のディレクトリオブジェクトであり、その先には実際に Oracle の稼働しているサーバーの物理パスを指しています。
SELECT * FROM DBA_DIRECTORIES WHERE DIRECTORY_NAME='DATA_PUMP_DIR';

ちなみに、この PATH の表記方法から想像つくように、RDS for Oracle の実体は Linux です。以下の SQL でこのデータベースサーバーのプラットフォームを確認できます。あとプラットフォームが Linux であるということはファイル名には「大文字小文字の区別がある」ということです。つまり、"readme.txt" と “Readme.txt" も “readme.TXT" もすべて別ファイルということです。Windows に慣れた人は戸惑うところですが、注意してください。
SELECT PLATFORM_NAME FROM V$DATABASE;

ディレクトリオブジェクトの作成
Linux なら /tmp に書き込めそうなので、以下のようなディレクトリオブジェクトを作成してみます。
CREATE DIRECTORY TMPDIR AS '/tmp';

あらら、失敗しましたね。どうやらディレクトリオブジェクトの作成は RDS 用のパッケージが用意されているようです。「Oracle DB インスタンスのその他のタスクの実行」に記載があります。
EXEC RDSADMIN.RDSADMIN_UTIL.CREATE_DIRECTORY('TMPDIR');
DBA_DIRCTORIES で確認すると確かに作成されています。さすがに物理パスの指定はできないということですね。

冒頭のサンプルの PL/SQL で宛先のディレクトリを DATA_PUMP_DIR から今回作成した TMPDIR に変更して実行してみます。実行後、ディレクトリ配下のファイルを参照してみたところ、ちゃんと作成されていました。
SELECT * FROM TABLE(RDSADMIN.RDS_FILE_UTIL.LISTDIR('TMPDIR'));

RDS ストレージに対するファイルの送受信
次に疑問になるのが、この RDS のストレージ上にあるファイルをどうやって取得すればいいのか、ですよね。あるいは、逆に RDS ストレージにどうやってファイルを送信すれば良いのか、とか。
これには以下の3つの方法があります。
- データベースリンクと DBMS_FILE_TRANSFER を利用して送受信する
- Amazon S3 バケットを経由して送受信する
- UTL_FILE.GET_RAW を使って受信、PUT_RAW を使って送信するプログラムを作成する
これらを少し解説します。
データベースリンクと DBMS_FILE_TRANSFER を利用して送受信する
これはあくまでもデーターベースからデータベースへの転送です。単に RDS 間でファイル転送したいだけなら、これを利用するのが一番良いと思います。ですが、RDS上のファイルを手元に受信したい、とか手元にあるファイルを RDS 上に送信したい、となると、すべてのデータベースが RDS に置き換わったとしたらできません。どこかにひとつだけオンプレ Oracle (EC2 上の Oracle 含む)が必要になります。
もちろん「本番環境の RDS からテスト環境の RDS にデータを移したい」とか「オンプレから RDS へデータ移行したい」というときには利用すると思いますので、環境を準備して別途検証したいと思います。
【2021.11.25 追記】検証記事を書きましたのでリンク貼っておきます。
Amazon S3 バケットを経由して取得する
Amazon S3 というのは、簡単に言えば Google Drive や Microsoft OneDrive と同じようなストレージサービスですね。RDS for Oracle に RDSADMIN_S3_TASKS パッケージというものがあり、これを利用して S3 バケットとファイルの送受信ができるようです。ただ、S3 といってもタダではありません。しかも「Amazon S3 の料金」を見ても分かりにくい、、、あんま気軽にやるものではなさそうですね。
ただ、こちらも通常運用時の定期バックアップ等では使えるかもしれません。RDS そのものにはバックアップ機能があるのですが、プロシジャで作成しているログや、EXPDP で特定のテーブルのみ日々バックアップする等のケースです。そうなると、仮に1週間分のダンプを保管しておく必要があるというのであれば、RDS のストレージ上にそのまま保管しておくより、S3 に移動しておく方が安いでしょうね。これも別途検証したいと思います。
UTL_FILE.GET_RAW を使って受信、PUT_RAW を使って送信するプログラムを作成する
UTL_FILE.GET_RAW 及び PUT_RAW を使って1回で最大32767バイトのバイナリデータをやりとりできます。ファイルそのものをやりとりするためには、サイズによっては複数回の読み書きが必要となり、どうしてもプログラムを作成する必要がでてきます。
PUT_RAW を使ったサンプルプログラムは、AWSホワイトペーパーである「Strategies for Migrating Oracle Databases to AWS」にあるのですが、GET_RAW はありません。あと、言語は Perl です。PUT_RAW を PowerShell で焼き直し、それを参考に GET_RAW も作ってます。以下の検証記事を参考にしてください。
最後に
RDS for Oracle 上のファイルの扱いについて少し書きましたが、基本的にはデータのエクスポート/インポートをイメージして書いています。Oracle の推奨しているユーティリティである EXPDP や IMPDP は、基本的にデータベースサーバ上のダンプファイルをターゲットにしているからです。
ただ、Amazon Relational Database Service (RDS) ユーザーガイドには Oracle では非推奨のはずのオリジナルのユーティリティ exp / imp の利用が選択肢のひとつになっています。
Oracle エクスポート/インポートユーティリティは、データサイズが小さく、2 進浮動小数点数や倍精度浮動小数点数などのデータ型を必要としない場合の移行に最適なツールです。インポートプロセスではスキーマオブジェクトが作成されるため、スキーマオブジェクトを事前に作成するためのスクリプトを実行する必要はありません。このプロセスは、小規模なテーブルを使用したデータベースに適しています。次の例では、これらのユーティリティを使用して、特定のテーブルのエクスポートやインポートを実行する方法について説明します。
Oracle エクスポート/インポートユーティリティ
それでは Oracle 19c のマニュアルにはどのように書いているでしょう。
ノート:オリジナルのエクスポートは、Oracle Database 11gからは原則としてサポートされなくなりました。Oracle Database 11gで唯一サポートされているオリジナルのエクスポートの使用法は、XMLTypeデータのOracle Database 10gリリース2 (10.2)以前への下位移行です。したがって、オリジナルのエクスポートおよびインポートが必要な次の場合を除いて、データ・ポンプ・エクスポートおよびインポート・ユーティリティを使用することをお薦めします。
オリジナルのエクスポート
・オリジナルのエクスポート・ユーティリティ(exp)を使用して作成されたファイルをインポートする必要がある。
・オリジナルのインポート・ユーティリティ(imp)を使用してインポートされるファイルをエクスポートする必要がある。このような例として考えられるのは、Oracle Database 10gからデータをエクスポートし、それより前のデータベース・リリースにインポートする場合です。
、、、、すいません、なんか禅問答というか哲学的でよくわかりませんね(笑)
下位互換が単なる例として記載されているということは、 RDS for Oracle に対するエクスポートが「オリジナルのエクスポート・ユーティリティ(exp)を使用する必要がある」と言えるかどうかってことですかね。でも、AWS 側のユーザーガイドには条件さえ満たせば「最適」って書いてるんだから、使って良いってことですかね。
個人的には、ちょっとしたデータの出し入れにはオリジナルのエクスポート、インポートを利用するぞ!と心に固く誓った今日この頃でした、、、、
ディスカッション
コメント一覧
まだ、コメントがありません