DBMS_PIPE自体はオラクル・データベースに古くから提供されているパッケージのようですが、私は使うのは初めてです。これまでは単一インスタンス内で共有メモリを介したメッセージのやり取りだけが可能でした。
Autonomous Databaseの23aiでは、メッセージの保存先にオブジェクト・ストレージのバケットを指定することにより、異なるインスタンス間でのメッセージのやり取りができるようになりました。
以下のように動作する簡単なAPEXアプリケーションを作ってみました。異なるインスタンスで同じAPEXアプリケーションを実行し、メッセージをやり取りしています。
実装するにあたって、以下のオラクルのドキュメントを参考にしています。
また、以下の記事も参考にしました。ただし、以下の記事では、セットアップが完了していません。実装中にこの記事と同じエラー(ORA-20404)が発生したのですが、何故か、エラーが発生しなくなりました。今の所、回避手順は不明です。バケット内にlockファイルが無いというエラーだったのですが、バケット内にlockファイルは残っていて、それを手作業で消したのが良かったのかもしれません。
Persistent, cross database and cross region pipe in Oracle Database 23ai
https://technology.amis.nl/oracle/persistent-cross-database-and-cross-region-pipe-in-oracle-database-23ai/
以下より実装手順を紹介します。
アプリケーションを作る前に、DBMS_PIPEでメッセージのやり取りを行うための準備をします。
https://technology.amis.nl/oracle/persistent-cross-database-and-cross-region-pipe-in-oracle-database-23ai/
以下より実装手順を紹介します。
アプリケーションを作る前に、DBMS_PIPEでメッセージのやり取りを行うための準備をします。
APEXのワークスペース・スキーマはデフォルトではパッケージDBMS_CLOUDとDBMS_PIPEの実行権限を持っていないため、ユーザーADMINでGRANT文を実行し、権限を付与します。
grant execute on dbms_cloud to <APEXワークスペース・スキーマ>;
grant execute on dbms_pipe to <APEXワークスペース・スキーマ>;
続いて、オブジェクト・ストレージにバケットを作成します。今回の例ではpipeというバケットを作成しています。バケットのURLは以下のようになります。バケット名が異なる場合は、pipeの部分を変更します。
https://[ネームスペース].objectstorage.[リージョン].oci.customer-oci.com/n/[ネームスペース]/b/pipe/o/
APEXからOCIオブジェクト・ストレージを操作する(1) - APIユーザーの作成
APIキーの追加時に取得したuser_ocid、tenancy_ocid、private_key、fingerprintの情報より、DBMS_CLOUD.CREATE_CREDENTIALを呼び出し、データベースにクリデンシャルを作成します。以下の例ではcredential_nameをORACLE_API_AGENTとしています。
あらかじめ、パブリック・パイプのPIPE_C2Pを作成します。
declare
l_status INTEGER;
begin
l_status := DBMS_PIPE.CREATE_PIPE(
pipename => 'PIPE_C2P'
,private => false
);
end;
空のAPEXアプリケーションを作成します。名前はSample DBMS_PIPEとします。
メッセージのやり取りは、ホーム・ページに実装します。
アプリケーション定義の置換として、クリデンシャル、バケット、パイプの名前を設定します。
クリデンシャルは置換文字列CREDENTIAL_NAME、バケットはBUCKET_URL、パイプはPIPE_NAMEの置換値として設定します。
ホーム・ページには2つのボタンSEND_MESSAGEとRECEIVE_MESSAGE、それとメッセージを入力するテキスト領域のページ・アイテムP1_MESSAGEを配置します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_result integer; | |
l_message varchar2(32767); | |
e_send_message_failed exception; | |
begin | |
dbms_pipe.set_credential_name(:CREDENTIAL_NAME); | |
dbms_pipe.set_location_uri(:BUCKET_URL); | |
dbms_pipe.pack_message(:P1_MESSAGE); | |
l_result := dbms_pipe.send_message( | |
pipename => :PIPE_NAME | |
,timeout => 3 | |
,credential_name => DBMS_PIPE.GET_CREDENTIAL_NAME | |
,location_uri => DBMS_PIPE.GET_LOCATION_URI | |
); | |
if l_result = 0 then | |
:P1_MESSAGE := ''; | |
else | |
raise e_send_message_failed; | |
end if; | |
end; |
ボタンRECEIVE_MESSAGEを押したときに実行されるプロセスとしてReceive Messageを作成し、以下のコードを記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_result integer; | |
l_message varchar2(32767); | |
begin | |
dbms_pipe.set_credential_name(:CREDENTIAL_NAME); | |
dbms_pipe.set_location_uri(:BUCKET_URL); | |
l_result := dbms_pipe.receive_message( | |
pipename => :PIPE_NAME | |
,timeout => 3 | |
,credential_name => DBMS_PIPE.GET_CREDENTIAL_NAME | |
,location_uri => DBMS_PIPE.GET_LOCATION_URI | |
); | |
if l_result = 0 then | |
dbms_pipe.unpack_message(l_message); | |
:P1_MESSAGE := l_message; | |
end if; | |
end; |
双方ともAutonomous Databaseの場合、インスタンス間での通信手段は他にもあります。データベース・リンクを経由したDBMS_AQによる通信は、DBMS_PIPEよりも高機能です。
DBMS_CLOUDパッケージを導入することで、オンプレの23aiともメッセージのやり取りができるかと考えて試してみましたが、できませんでした。オンプレ版のデータベースへのDBMS_CLOUDのインストールはサポートのドキュメントHow To Setup And Use DBMS_CLOUD Package (ドキュメントID 2748362.1)で紹介されていますが、 「This package is supported in Oracle Database 19c beginning with 19.9 and in Oracle Database 21c beginning with 21.3.」となっていて、23が含まれていません。そのあたりに問題がありそうです。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/sample-dbms-pipe.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完