2022年2月18日金曜日

AQを使ってバックグランドでジョブを実行する - 通知の代わりにジョブを使う

 以前に書いた記事でAQの通知を使ってバックグランド処理を行うようにしていのたですが、やはりバックグランド処理の並列度は制御したいので、通知ではなくDBMS_SCHEDULERでジョブを作成して処理する方法を試してみました。

特にAlways Freeのインスタンスはスレッドが2本なので、バックグラウンドで長時間実行されるジョブが何本もあると、画面操作が進まなくなってしまいます。

以下、作業手順になります。作成済みの通知、キュー、キュー表は削除しておきます。また、アプリケーションは作成済みのものを改修します。

最初にキュー表とキューを作成します。通知は使わないので、シングル・コンシューマで十分です。タイプjob_message_tが作成済みであれば、キュー表とキューの作成と開始を行うPL/SQLブロックのみ実行します。

通知で呼び出されるプロシージャexec_jobを、DBMS_SCHDULERのジョブとして呼び出すためのラッパーとなるプロシージャexec_job0を作成します。DBMS_SCHEDULER.CREATE_PROGRAMを呼び出して、exec_job0を呼び出すプログラムMEX_SAMPLE_PROCを作成します。続いてDBMS_SCHEDULER.CREATE_JOBを呼び出して、ジョブMEX_WORKER_JOB01を作成し開始します。

作成済みのアプリケーションに含まれる、ジョブのリクエストをエンキューするコードを変更します。変更するコードの全体が以下になりますが、変更点は1行だけです。

dequeue_options.consumer_nameの指定をコメント・アウトしています。

ページ番号3にあるプロセスジョブの投入PL/SQLコードを置き換えます。

以上で変更は完了です。

同じジョブを同時に実行することで、並列度を上げることができます。

すこしアプリケーションに不具合がありました。行の削除時に表示されるメッセージを抑制するためのプロセスを追加します。

プロセスジョブの投入の直前で実行されるプロセスメッセージの初期化を作成します。PL/SQLコードには、以下を記述します。

:AI_SUCCESS_MESSAGE := '';


以上で、バックグラウンドの処理が通知ではなくジョブで行われるようになりました。アプリケーションの動作に違いはありません。(ジョブの処理に時間がかかるようになっています)。

作成されたジョブは、ビューUSER_SCHEDULER_JOBSより確認できます。

select * from user_scheduler_jobs;

作成したDBMS_SCHEDULERジョブやプログラムを削除するコードを書いています。

以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。