如何创建异步Oracle作业以在多个实例中运行

时间:2016-12-26 11:52:32

标签: oracle scheduler oracle12c job-scheduling

我创建了下一个程序和后续的Oracle JOB:

BEGIN
   DBMS_SCHEDULER.create_program (program_name          => 'myProg',
                                  program_action        => 'myProc',
                                  program_type          => 'STORED_PROCEDURE',
                                  number_of_arguments   => 3,
                                  enabled               => FALSE);

   DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT (program_name        => 'myProg',
                                           argument_position   => 1,
                                           argument_type       => 'NUMBER');

   DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT (program_name        => 'myProg',
                                           argument_position   => 2,
                                           argument_type       => 'NUMBER');

   DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT (program_name        => 'myProg',
                                           argument_position   => 3,
                                           argument_type       => 'NUMBER',
                                           DEFAULT_VALUE       => NULL);

   DBMS_SCHEDULER.create_job ('myJob',
                              program_name   => 'myProg',
                              enabled        => FALSE,
                              comments       => 'Send data');

   DBMS_SCHEDULER.SET_ATTRIBUTE ('myJob', 'PARALLEL_INSTANCES', TRUE);
   DBMS_SCHEDULER.SET_ATTRIBUTE ('myJob',
                                 'logging_level',
                                 DBMS_SCHEDULER.LOGGING_FULL);
END;
/

现在,我有一个用户可以运行/执行调用下一个过程的作业:

    PROCEDURE runJOB(param1   IN PLS_INTEGER,
                  param2   IN PLS_INTEGER DEFAULT NULL,
                  param3   IN PLS_INTEGER DEFAULT NULL)
IS
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   DBMS_SCHEDULER.enable ('myProg');

   DBMS_SCHEDULER.set_job_argument_value ('myJob', 1, TO_CHAR (param1));
   DBMS_SCHEDULER.set_job_argument_value ('myJob', 2, TO_CHAR (param2));
   DBMS_SCHEDULER.set_job_argument_value ('myJob', 3, TO_CHAR (param3));
   --DBMS_SCHEDULER.enable ('myJob');
   DBMS_SCHEDULER.RUN_JOB (JOB_NAME => 'myJob', USE_CURRENT_SESSION => FALSE);
--DBMS_SCHEDULER.disable ('myJob');
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line (DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END runJOB;

这里有什么问题?

  • 我需要以异步模式运行作业。这就是为什么我有一个 使用enable参数的run_jobUSE_CURRENT_SESSION FALSE。我认为这很有效。
  • 我需要从头开始执行同一作业的多个实例 不同的用户,同时。例如,用户A调用 runJOB程序。这项工作可以在20秒内完成。在这20 秒,用户B可以在不同的会话中调用相同的过程。 这就是为什么我尝试使用PARALLEL_INSTANCES属性,但是 我只得到一次执行。我认为Oracle认为这项工作是 跑步,所以放弃第二次跑步的尝试。

在恢复中,我需要一个必须在异步模式下执行并且同时具有多个实例的作业。

在两个实例的“双重”执行作业之后,我只在user_SCHEDULER_JOB_RUN_DETAILS表中获得一条记录,但是为两个不同的用户启用了2个作业(SGSS和EX01882_BD)

52367532    26/12/2016 12:08:44,584878 +00:00   SGSS    myJob DEFAULT_JOB_CLASS RUN SUCCEEDED                               (HugeClob)
52364238    26/12/2016 12:08:36,529539 +00:00   SGSS    myJob DEFAULT_JOB_CLASS ENABLE      EX01882_BD                          (HUGECLOB)
52367534    26/12/2016 12:08:34,302807 +00:00   SGSS    myJob DEFAULT_JOB_CLASS ENABLE      SGSS                            (HUGECLOB)

任何帮助?

注意: 我不能在此解决方案(How run two or more instances of an oracle job in the same time?)中拥有作业的不同名称,因为作业已经创建,并且调用此作业的用户无权创建。

2 个答案:

答案 0 :(得分:1)

  

DBMS_SCHEDULER.RUN_JOB(JOB_NAME =>'myJob',USE_CURRENT_SESSION =>   的 FALSE );

现在,检查documentation

  

指定作业是否应该在同一个中运行   从中调用过程的会话。

     

当use_current_session设置为TRUE时:

     
      
  • 作业以调用RUN_JOB的用户身份运行,或者在具有凭据的本地外部作业的情况下,以用户身份命名的用户   凭证。

  •   
  • 您可以在命令行上测试作业并查看任何可能的错误。

  •   
  • run_count,last_start_date,last_run_duration和failure_count不会更新。

  •   
  • RUN_JOB可以与定期计划的作业并行运行。

  •   
     

当use_current_session设置为FALSE时:

     
      
  • 作业以作业所有者的身份运行。

  •   
  • 您需要检查作业日志以查找错误信息。

  •   
  • run_count,last_start_date,last_run_duration和failure_count已更新。

  •   
  • 如果正在计划的作业正在运行,则RUN_JOB会失败。

  •   

答案 1 :(得分:1)

解决方案:Event-Based Jobs

GRANT AQ_ADMINISTRATOR_ROLE TO USERA;
GRANT EXECUTE ON DBMS_SCHEDULER TO USERA;
GRANT EXECUTE ON sys.DBMS_SCHEDULER TO USERA;
GRANT EXECUTE ON sys.DBMS_ISCHED TO USERA;
GRANT CREATE JOB TO USERA;
GRANT CREATE EXTERNAL JOB TO USERA;

CREATE OR REPLACE TYPE t_event_queue_payload AS OBJECT (
  event_name  VARCHAR2(30)
);

BEGIN
   -- Create a queue table to hold the event queue.
   DBMS_AQADM.create_queue_table (
      queue_table          => 'event_queue_tab',
      queue_payload_type   => 't_event_queue_payload',
      multiple_consumers   => TRUE,
      comment              => 'Comments');

   --Create the event queue.
   DBMS_AQADM.create_queue (queue_name    => 'event_queue',
                            queue_table   => 'event_queue_tab');

   -- Start the event queue.
   DBMS_AQADM.start_queue (queue_name => 'event_queue');
END;
/


BEGIN
   DBMS_SCHEDULER.create_program (
      program_name          => 'myProg',
      program_action        => 'USERA.PACKAGE.myProc',
      program_type          => 'STORED_PROCEDURE',
      number_of_arguments   => 3,
      enabled               => FALSE);

   DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT (program_name        => 'myProg',
                                           argument_position   => 1,
                                           argument_type       => 'NUMBER');

   DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT (program_name        => 'myProg',
                                           argument_position   => 2,
                                           argument_type       => 'NUMBER');

   DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT (program_name        => 'myProg',
                                           argument_position   => 3,
                                           argument_type       => 'NUMBER',
                                           DEFAULT_VALUE       => NULL);

   DBMS_SCHEDULER.enable ('myProg');
   DBMS_SCHEDULER.create_job (
      'myJob',
      program_name      => 'myProg',
      comments          => 'StartJob',
      auto_drop         => FALSE,
      start_date        => SYSTIMESTAMP,
      event_condition   => 'tab.user_data.event_name = ''give_me_a_prod''',
      queue_spec        => 'event_queue',
      enabled           => FALSE);

   COMMIT;
END;
/

PROCEDURE enqueue(param1   IN PLS_INTEGER,
                  param2   IN PLS_INTEGER DEFAULT NULL,
                  param3   IN PLS_INTEGER DEFAULT NULL)
IS
   PRAGMA AUTONOMOUS_TRANSACTION;
   l_enqueue_options      DBMS_AQ.ENQUEUE_OPTIONS_T;
   l_message_properties   DBMS_AQ.MESSAGE_PROPERTIES_T;
   l_message_handle       RAW (16);
   l_queue_msg            t_event_queue_payload;
BEGIN
   l_queue_msg := t_event_queue_payload ('give_me_a_prod');

   -- Define arguments
   DBMS_SCHEDULER.set_job_argument_value ('myJob', 1, TO_CHAR (param1));
   DBMS_SCHEDULER.set_job_argument_value ('myJob', 2, TO_CHAR (param2));
   DBMS_SCHEDULER.set_job_argument_value ('myJob', 3, TO_CHAR (param3));

   DBMS_AQ.enqueue (queue_name           => 'USERA.event_queue',
                    enqueue_options      => l_enqueue_options,
                    message_properties   => l_message_properties,
                    payload              => l_queue_msg,
                    msgid                => l_message_handle);

   COMMIT;
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line (
         SQLERRM || ' - ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END enqueue;

在包装中:

PROCEDURE myProc(param1   IN PLS_INTEGER,
                  param2   IN PLS_INTEGER DEFAULT NULL,
                  param3   IN PLS_INTEGER DEFAULT NULL)
IS
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
...
   PKG_SAP_FSCD_INTERRECIBOS.callSomething.... 
...

END myProc;