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

How to create a async Oracle job to run in multiple instances

我已经创建了下一个程序和后续的 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;
/

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

    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;

我的问题是什么?

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

在为两个实例执行作业 "double" 后,我只在 user_SCHEDULER_JOB_RUN_DETAILS table 中获得一条记录,但是 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?) 中不同的作业名称,因为作业已经创建并且调用此作业的用户没有创建权限。

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

现在,检查 documentation

This specifies whether or not the job run should occur in the same session that the procedure was invoked from.

When use_current_session is set to TRUE:

  • The job runs as the user who called RUN_JOB, or in the case of a local external job with a credential, the user named in the
    credential.

  • You can test a job and see any possible errors on the command line.

  • run_count, last_start_date, last_run_duration, and failure_count are not updated.

  • RUN_JOB can be run in parallel with a regularly scheduled job run.

When use_current_session is set to FALSE:

  • The job runs as the user who is the job owner.

  • You need to check the job log to find error information.

  • run_count, last_start_date, last_run_duration, and failure_count are updated.

  • RUN_JOB fails if a regularly scheduled job is running.

解决方案: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;