ZZ3111
ZZ3111

Reputation: 87

Run procedures in parallel - Oracle PL/SQL

I am trying to run stored procedures in parallel - Oracle PL/SQL using dbms_scheduler but I am getting an error like an unknown job, I have also tried dbms_job, here I am getting an error- identifier dbms_jobs must be declared. Could someone please help me out? Below are two approaches I have tried:

CREATE PACKAGE BODY pkg IS
CREATE PROCEDURE do_parallel_execution
IS
BEGIN
   DBMS_SCHEDULER.RUN_JOB('pkg1.proc1', false);
   DBMS_SCHEDULER.RUN_JOB('pkg1.proc2', false);
   DBMS_SCHEDULER.RUN_JOB('pkg1.proc3', false);
END;

CREATE PACKAGE BODY pkg IS
CREATE PROCEDURE run_in_parallel
IS
   l_jobno pls_integer;
BEGIN
   dbms_job.submit(l_jobno, 'pkg1.proc1; end;' );
   dbms_job.submit(l_jobno, 'pkg1.proc2; end;' );
  -- dbms_job.submit(l_jobno, 'pkg1.proc3; end;' );
END;

where pkg1 has all 3 procedures defined in it. Thank you!

Upvotes: 4

Views: 10351

Answers (2)

mubasheer
mubasheer

Reputation: 11

The parallel processing can be achieved using the schedule job chain.

  1. create schedule programs with the procedure function you want to run,
  2. create a scheduler chain and define steps and rules,
  3. create a job/scheduler job to call the scheduler chain

Upvotes: 0

pmdba
pmdba

Reputation: 7033

To execute otherwise unrelated procedures in parallel, use a Scheduler Job Chain:

Create procedures:

create or replace package test as
    procedure test1;
    procedure test2;
    procedure test3;
end test;
/

create or replace package body test as
    procedure test1 is
    begin
        sys.dbms_session.sleep(5);
    end test1;

    procedure test2 is
    begin
        sys.dbms_session.sleep(5);
    end test2;

    procedure test3 is
    begin
        sys.dbms_session.sleep(5);
    end test3;
end test;
/

Create Scheduler Programs for each procedure:

BEGIN
    DBMS_SCHEDULER.create_program(
        program_name => 'TEST1_PROGRAM',
        program_action => 'TEST.TEST1',
        program_type => 'STORED_PROCEDURE',
        number_of_arguments => 0,
        comments => NULL,
        enabled => FALSE);

    DBMS_SCHEDULER.ENABLE(name=>'TEST1_PROGRAM');    

    DBMS_SCHEDULER.create_program(
        program_name => 'TEST2_PROGRAM',
        program_action => 'TEST.TEST2',
        program_type => 'STORED_PROCEDURE',
        number_of_arguments => 0,
        comments => NULL,
        enabled => FALSE);

    DBMS_SCHEDULER.ENABLE(name=>'TEST2_PROGRAM');    

    DBMS_SCHEDULER.create_program(
        program_name => 'TEST3_PROGRAM',
        program_action => 'TEST.TEST3',
        program_type => 'STORED_PROCEDURE',
        number_of_arguments => 0,
        comments => NULL,
        enabled => FALSE);

    DBMS_SCHEDULER.ENABLE(name=>'TEST3_PROGRAM');    
END;
/

Create the Scheduler Chain:

BEGIN
  -- one step for each program
  SYS.DBMS_SCHEDULER.DEFINE_CHAIN_STEP (
     chain_name          => 'TEST_CHAIN'
    ,step_name           => 'CHAIN_STEP1'
    ,program_name        => 'TEST1_PROGRAM');

  SYS.DBMS_SCHEDULER.DEFINE_CHAIN_STEP (
     chain_name          => 'TEST_CHAIN'
    ,step_name           => 'CHAIN_STEP2'
    ,program_name        => 'TEST2_PROGRAM');

  SYS.DBMS_SCHEDULER.DEFINE_CHAIN_STEP (
     chain_name          => 'TEST_CHAIN'
    ,step_name           => 'CHAIN_STEP3'
    ,program_name        => 'TEST3_PROGRAM');

  -- one rule with condition "true" to start each step immediately
  SYS.DBMS_SCHEDULER.DEFINE_CHAIN_RULE  (
      CHAIN_NAME  => 'TEST_CHAIN',
      rule_name  => 'TEST_RULE1',
      condition => 'TRUE',
      action => 'START "CHAIN_STEP1"');   

  SYS.DBMS_SCHEDULER.DEFINE_CHAIN_RULE  (
      CHAIN_NAME  => 'TEST_CHAIN',
      rule_name  => 'TEST_RULE2',
      condition => 'TRUE',
      action => 'START "CHAIN_STEP2"');   

  SYS.DBMS_SCHEDULER.DEFINE_CHAIN_RULE  (
      CHAIN_NAME  => 'TEST_CHAIN',
      rule_name  => 'TEST_RULE3',
      condition => 'TRUE',
      action => 'START "CHAIN_STEP3"');   

  -- one rule to close out the chain after all steps are completed    
  SYS.DBMS_SCHEDULER.DEFINE_CHAIN_RULE (
     chain_name          => 'TEST_CHAIN',
     rule_name           => 'TEST_RULE4',
     condition           => 'CHAIN_STEP1 Completed AND CHAIN_STEP2 Completed AND CHAIN_STEP3 Completed',
     action              => 'END 0');

END;
/

The chain flow now looks like this (as depicted by SQL Developer):

enter image description here

Now create a Scheduler Job to run the chain:

BEGIN
    DBMS_SCHEDULER.CREATE_JOB (
            job_name => 'TEST_JOB',
            job_type => 'CHAIN',
            job_action => 'TEST_CHAIN',
            number_of_arguments => 0,
            start_date => NULL,
            repeat_interval => NULL,
            end_date => NULL,
            enabled => FALSE,
            auto_drop => FALSE,
            comments => '');

    DBMS_SCHEDULER.SET_ATTRIBUTE( 
             name => 'TEST_JOB', 
             attribute => 'logging_level', value => DBMS_SCHEDULER.LOGGING_RUNS);

END;
/

And run the job:

BEGIN
    DBMS_SCHEDULER.RUN_JOB(job_name => 'TEST_JOB', USE_CURRENT_SESSION => FALSE);
END;
/

Now look at the job run details for the job:

"LOG_ID" "LOG_DATE"                               "JOB_NAME" "JOB_SUBNAME" "STATUS"    "ERROR#" "ACTUAL_START_DATE"                                "RUN_DURATION"
"1548"   "14-JUN-20 12.15.46.744612000 AM -04:00" "TEST_JOB" "CHAIN_STEP3" "SUCCEEDED" "0"      "14-JUN-20 12.15.41.708043000 AM AMERICA/NEW_YORK" "+00 00:00:05.000000"
"1544"   "14-JUN-20 12.15.46.746544000 AM -04:00" "TEST_JOB" "CHAIN_STEP2" "SUCCEEDED" "0"      "14-JUN-20 12.15.41.690404000 AM AMERICA/NEW_YORK" "+00 00:00:05.000000"
"1546"   "14-JUN-20 12.15.46.748830000 AM -04:00" "TEST_JOB" "CHAIN_STEP1" "SUCCEEDED" "0"      "14-JUN-20 12.15.41.690891000 AM AMERICA/NEW_YORK" "+00 00:00:05.000000"
"1550"   "14-JUN-20 12.15.46.968592000 AM -04:00" "TEST_JOB" ""            "SUCCEEDED" "0"      "14-JUN-20 12.15.41.574115000 AM AMERICA/NEW_YORK" "+00 00:00:05.000000"

Note that:

  • The job starts at "12.15.41.574115000" (ACTUAL_START_DATE, Line 1550).

  • Each job step starts within a fraction of a second of the overall job start (as recorded in ACTUAL_START_DATE for each step in lines 1544, 1546, and 1548), and completes in the expected 5 seconds.

  • The overall job completes at "14-JUN-20 12.15.46.968592000" (LOG_DATE, Line 1550) with a total duration of 5 seconds to complete all three steps.

  • Note that rule processing may add a tiny bit of overhead to the total execution time for the chain.

Upvotes: 9

Related Questions