在Oracle 11g中进行同步和异步MView刷新的更好方法是什么?

时间:2015-11-03 17:19:05

标签: oracle asynchronous oracle11g synchronous

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

其中五个是独立于数据源的,可以异步重建。

其中两个依赖于前五个MView中的一些,需要等到刷新后再进行刷新。最后两个是相互独立的,可以异步运行。

我最初问过这个问题here。我的计划是去DBMS_JOB.SUBMIT路线。有人向我解释过,DBMS_JOB.SUBMIT是一个解决这个问题的Oracle 8级方法,我应该考虑使用DBMS_SCHEDULER。

我的问题变为:在Oracle 11g中进行同步和异步MView刷新的更好方法是什么?

我想分享我用过的DBMS_SCHEDULER解决方案,以防任何人对在Oracle 11g中使用同步和异步方法调用的更好方法感兴趣。

1 个答案:

答案 0 :(得分:2)

TLDR:

  1. 使用DBMS_SCHEDULER.CREATE_PROGRAM创建命名程序。
  2. 使用DBMS_SCHEDULER.CREATE_CHAIN创建链。
  3. 使用DBMS_SCHEDULER.DEFINE_CHAIN_STEP定义链中的步骤,以调用在#1中创建的命名程序。
  4. 使用DBMS_SCHEDULER.DEFINE_CHAIN_RULE来定义何时调用步骤(这是定义同步和异步调用的地方)。
  5. 使用DBMS_SCHEDULER.CREATE_SCHEDULE创建计划,以确定#6中创建的作业何时运行。
  6. 使用DBMS_SCHEDULER.CREATE_JOB创建一个作业,该作业将根据#5中创建的计划运行,以执行#2中创建的链。
  7. 代码:

    -- First: Create the programs to refresh the MViews
    BEGIN
      -- Independent Programs
      DBMS_SCHEDULER.CREATE_PROGRAM (
          program_name => 'PROGRAM_REFRESH_MVIEW_I1', 
          program_action => 'BEGIN DBMS_MVIEW.REFRESH(list => ''IndependentMView1'', METHOD => ''C'') ; END;', 
          program_type => 'PLSQL_BLOCK', 
          number_of_arguments => 0, 
          comments => 'This Refreshes the IndependentMView1 MView.', 
          enabled => TRUE) ;
      DBMS_SCHEDULER.CREATE_PROGRAM (
          program_name => 'PROGRAM_REFRESH_MVIEW_I2', 
          program_action => 'BEGIN DBMS_MVIEW.REFRESH(list => ''IndependentMView2'', METHOD => ''C'') ; END;', 
          program_type => 'PLSQL_BLOCK', 
          number_of_arguments => 0, 
          comments => 'This Refreshes the IndependentMView2 MView.', 
          enabled => TRUE) ;
      DBMS_SCHEDULER.CREATE_PROGRAM (
          program_name => 'PROGRAM_REFRESH_MVIEW_I3', 
          program_action => 'BEGIN DBMS_MVIEW.REFRESH(list => ''IndependentMView3'', METHOD => ''C'') ; END;', 
          program_type => 'PLSQL_BLOCK', 
          number_of_arguments => 0, 
          comments => 'This Refreshes the IndependentMView3 MView.', 
          enabled => TRUE) ;
      DBMS_SCHEDULER.CREATE_PROGRAM (
          program_name => 'PROGRAM_REFRESH_MVIEW_I4', 
          program_action => 'BEGIN DBMS_MVIEW.REFRESH(list => ''IndependentMView4'', METHOD => ''C'') ; END;', 
          program_type => 'PLSQL_BLOCK', 
          number_of_arguments => 0, 
          comments => 'This Refreshes the IndependentMView4 MView.', 
          enabled => TRUE) ;
      DBMS_SCHEDULER.CREATE_PROGRAM (
          program_name => 'PROGRAM_REFRESH_MVIEW_I5', 
          program_action => 'BEGIN DBMS_MVIEW.REFRESH(list => ''IndependentMView5'', METHOD => ''C'') ; END;', 
          program_type => 'PLSQL_BLOCK', 
          number_of_arguments => 0, 
          comments => 'This Refreshes the IndependentMView5 MView.', 
          enabled => TRUE) ;
    
      -- Dependent Programs
      DBMS_SCHEDULER.CREATE_PROGRAM (
          program_name => 'PROGRAM_REFRESH_MVIEW_D1', 
          program_action => 'BEGIN DBMS_MVIEW.REFRESH(list => ''DependentMView1'', METHOD => ''C'') ; END;', 
          program_type => 'PLSQL_BLOCK', 
          number_of_arguments => 0, 
          comments => 'This Refreshes the DependentMView1 MView.', 
          enabled => TRUE) ;
      DBMS_SCHEDULER.CREATE_PROGRAM (
          program_name => 'PROGRAM_REFRESH_MVIEW_D2', 
          program_action => 'BEGIN DBMS_MVIEW.REFRESH(list => ''DependentMView2'', METHOD => ''C'') ; END;', 
          program_type => 'PLSQL_BLOCK', 
          number_of_arguments => 0, 
          comments => 'This Refreshes the DependentMView2 MView.', 
          enabled => TRUE) ;
    END;
    
    /
    
    -- Next: Create the chain to control the refresh steps
    BEGIN
      DBMS_SCHEDULER.CREATE_CHAIN (
      chain_name => 'REFRESH_MVIEWS_CHAIN', 
      rule_set_name => NULL, 
      evaluation_interval => NULL, 
      comments => 'Refresh the Materialized Views in the correct order.') ;
    END;
    
    /
    
      -- Next: Create the steps used to call the programs to refresh the MViews. 
      -- Note: Referenced programs must be enabled.
    BEGIN
      DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('REFRESH_MVIEWS_CHAIN', 'stepI1', 'PROGRAM_REFRESH_MVIEW_I1') ;
      DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('REFRESH_MVIEWS_CHAIN', 'stepI2', 'PROGRAM_REFRESH_MVIEW_I2') ;
      DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('REFRESH_MVIEWS_CHAIN', 'stepI3', 'PROGRAM_REFRESH_MVIEW_I3') ;
      DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('REFRESH_MVIEWS_CHAIN', 'stepI4', 'PROGRAM_REFRESH_MVIEW_I4') ;
      DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('REFRESH_MVIEWS_CHAIN', 'stepI5', 'PROGRAM_REFRESH_MVIEW_I5') ;
    
      -- stepD1 is dependent on IndependentMView1, IndependentMView2, IndependentMView3
      DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('REFRESH_MVIEWS_CHAIN', 'stepD1', 'PROGRAM_REFRESH_MVIEW_D1') ;
      -- stepD2 is dependent on IndependentMView1, IndependentMView4
      DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('REFRESH_MVIEWS_CHAIN', 'stepD2', 'PROGRAM_REFRESH_MVIEW_D2') ;
    END;
    
    /
    
    -- Next: Define rules for the chain.  This is where we establish the 
    -- synchronous and asynchronous order of things. (i.e. where the magic happens)
    BEGIN
      -- First, start all independent steps asynchronously
      DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('REFRESH_MVIEWS_CHAIN', 'TRUE', 'START stepI1, stepI2, stepI3, stepI4, stepI5') ;
      -- Next, start dependent steps as their related independent steps complete.
      DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('REFRESH_MVIEWS_CHAIN', 'stepI1 COMPLETED AND stepI2 COMPLETED AND stepI3 COMPLETED', 'START stepD1') ;
      DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('REFRESH_MVIEWS_CHAIN', 'stepI1 COMPLETED AND stepI4 COMPLETED', 'Start stepD2') ;
      -- Last, define when the chain is complete.
      -- In this case, we're done when both dependent steps and the one independent step that no other steps are dependent upon are all complete.
      DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('REFRESH_MVIEWS_CHAIN', 'stepI5 COMPLETED AND stepD1 COMPLETED AND stepD2 COMPLETED', 'END') ;
    
      -- Enable the chain
      DBMS_SCHEDULER.ENABLE ('REFRESH_MVIEWS_CHAIN') ;
    END;
    
    /
    
    -- Next: create a schedule to run every 30 minutes at the top and bottom of every hour
    BEGIN
      DBMS_SCHEDULER.CREATE_SCHEDULE ( 
          schedule_name => 'THIRTY_MINUTE_SCHEDULE', 
          repeat_interval => 'FREQ=MINUTELY;INTERVAL=30', 
          start_date => TO_TIMESTAMP_TZ ('2015-11-2 0:0:00.000000000 UTC', 'YYYY-MM-DD HH24:MI:SS.FF TZR'), 
          comments => 'Fires at the top and bottom of every hour') ;
    END;
    
    /
    
    -- Lastly: Create a job to start the REFRESH_MVIEWS_CHAIN chain based on the THIRTY_MINUTE_SCHEDULE created above.
    BEGIN
      DBMS_SCHEDULER.CREATE_JOB (
          job_name => 'REFRESH_MVIEWS_JOB', 
          job_type => 'CHAIN', 
          job_action => 'REFRESH_MVIEWS_CHAIN', 
          schedule_name => 'TEN_TILL_TOP_BOTTOM_SCHEDULE', 
          number_of_arguments => 0, 
          enabled => FALSE, 
          auto_drop => FALSE, 
          comments => 'Refresh the Materialized Views');
    
      DBMS_SCHEDULER.SET_ATTRIBUTE (
          name => 'REFRESH_MVIEWS_JOB', 
          attribute => 'logging_level', 
          value => DBMS_SCHEDULER.LOGGING_OFF) ;
    
      -- Enable the refresh job
      DBMS_SCHEDULER.ENABLE (name => 'REFRESH_MVIEWS_JOB') ;
    END;
    
    /
    

    沿途有用的链接: