Oracle dbms_job.submit:混合同步和异步

Oracle dbms_job.submit: Mixing Synchronous and Asynchronous

我有 7 个物化视图需要按计划刷新。

其中五个与数据源无关,可以异步重建。我想使用 Tom 描述的东西 here

PROCEDURE refresh_Independent_MViews AS
l_job       BINARY_INTEGER;
BEGIN
  dbms_job.submit (l_job, 'DBMS_MVIEW.REFRESH(list => ''IndependentMView1'', method => ''C'') ;') ;
  dbms_job.submit (l_job, 'DBMS_MVIEW.REFRESH(list => ''IndependentMView2'', method => ''C'') ;') ;
  dbms_job.submit (l_job, 'DBMS_MVIEW.REFRESH(list => ''IndependentMView3'', method => ''C'') ;') ;
  dbms_job.submit (l_job, 'DBMS_MVIEW.REFRESH(list => ''IndependentMView4'', method => ''C'') ;') ;
  dbms_job.submit (l_job, 'DBMS_MVIEW.REFRESH(list => ''IndependentMView5'', method => ''C'') ;') ;
END refresh_Independent_MViews;

其中两个依赖于前五个 MView 中的一些,需要等到它们被刷新。最后这两个相互独立,可以同时运行

PROCEDURE refresh_Dependent_MViews AS
l_job       BINARY_INTEGER;
BEGIN
  dbms_job.submit (l_job, 'DBMS_MVIEW.REFRESH(list => ''DependentMView1'', method => ''C'') ;') ;
  dbms_job.submit (l_job, 'DBMS_MVIEW.REFRESH(list => ''DependentMView2'', method => ''C'') ;') ;
END refresh_Dependent_MViews;

问题:在启动异步作业完成工作后很快调用 "refresh_Independent_MViews" returns,但我无法判断各个异步作业何时全部完成工作。

问题:有没有办法知道 dbms_job.submit 启动的异步作业何时全部完成,以便我知道何时开始 "refresh_Dependent_MViews" 程序?

最简单的方法是从 dbms_job.submit 获取 l_job 输出参数,然后编写一个循环来检查 job 中有多少值在 dba_jobs,当计数为 0 时退出,否则通过调用 dbms_lock.sleep 休眠一段合理的时间。显然,您需要避免覆盖当前的 l_job 变量才能捕获所有五个作业。像

CREATE TYPE num_tbl
    AS TABLE OF NUMBER;

PROCEDURE refresh_all_MViews AS
  l_job       BINARY_INTEGER;
  l_jobs      num_tbl;
BEGIN
  l_jobs.extend(5);
  dbms_job.submit (l_job, ...) ;
  l_jobs(1) := l_job;
  dbms_job.submit (l_job, ...) ;
  l_jobs(2) := l_job;
  dbms_job.submit (l_job, ...) ;
  l_jobs(3) := l_job;
  dbms_job.submit (l_job, ...) ;
  l_jobs(4) := l_job;
  dbms_job.submit (l_job, ...) ;
  l_jobs(5) := l_job;

  loop
    select count(*)
      into l_cnt
      from dba_jobs
     where job in (select column_value from table(l_jobs));

    if( l_cnt = 0 )
    then
      exit;
    end if;

    dbms_lock.sleep( 10 ); -- Sleep for 10 seconds
  end loop;

  refresh_Dependent_MViews;

END refresh_all_MViews;

现在,您显然可以将 refresh_Independent_MViews 过程修改为 return 需要监视的作业编号集合,以便 refresh_all_mviews 过程调用 refresh_independent_mviews,执行循环,然后调用 refresh_dependent_mviews

您可以通过将作业写入记录成功或失败的 table 或通过 Oracle AQ 发送消息让另一个进程侦听以启动相关的 mview 刷新来变得更加复杂。在这种情况下可能不需要,但如果您的依赖关系变得更加复杂,则可能需要。毫无疑问,您还可以创建一个 dbms_scheduler 链来为您执行此操作。

使用 DBMS_SCHEDULER 链、步骤和命名程序是同步和异步刷新 MView 的更好方法。一方面,它提供了精确的时序控制。