Frage

I've trying to figure out oracle's DBMS_SCHEDULER (Oracle 11g) and need help setting up the following:

I have a procedure that calls a list of other procedures like this:

CREATE OR REPLACE
PROCEDURE RUN_JOBS AS
BEGIN
  MYUSER.MYPROCEDURE1();
  MYUSER.MYPROCEDURE2();
  MYUSER.MYPROCEDURE3();
  MYUSER.MYPROCEDURE4();
  MYUSER.MYPROCEDURE5();
END;
/

I would like to use DBMS_SCHEDULER to run MYPROCEDURE3(), MYPROCEDURE4(), MYPROCEDURE5() in parallel after the completion of MYPROCEDURE2().

Can someone show me an example on how to set this up?

War es hilfreich?

Lösung

You can refer to Chains under the DBMS_SCHEDULER package: http://docs.oracle.com/cd/B28359_01/server.111/b28310/scheduse009.htm

You can also achieve the same by going through Oracle Enterprise Manager, but I can't find any links to documentation right now.

Andere Tipps

You can do that using DBMS_SCHEDULER.

CREATE OR REPLACE PROCEDURE RUN_JOBS
AS
v_JobNum NUMBER := 1;
BEGIN
 BEGIN
  DBMS_JOB.SUBMIT(v_JobNum,'MYUSER.MYPROCEDURE1;',sysdate,'sysdate +1');
  DBMS_JOB.SUBMIT(v_JobNum,'MYUSER.MYPROCEDURE2;',sysdate,'sysdate +1');
  DBMS_JOB.SUBMIT(v_JobNum,'MYUSER.MYPROCEDURE3;',sysdate,'sysdate +1');
  DBMS_JOB.SUBMIT(v_JobNum,'MYUSER.MYPROCEDURE4;',sysdate,'sysdate +1');
  COMMIT;
 END;
END RUN_JOBS; 
/

This will submit the job and run them immediately.

create three different jobs for each procedure and schedule them at same time.

Here is my custom approach to parallellize work into N separate jobs retaining dbms_scheduler's logging and backpressure support. Date intervals are spread by mod N.

create table message_fixup_log (
    source_date date not null,
    started_at timestamp(6) not null,
    finished_at timestamp(6),
    fixed_message_count number(10)
);
alter table message_fixup_log add duration as (finished_at - started_at);
create unique index ix_message_fixup_log_date on message_fixup_log(source_date desc);

create or replace procedure message_fixup(jobNumber number, jobCount number, jobName varchar default null)
is
    minSince date;
    maxSince date;
    since date;
    msgUpdatedCount number;
begin
    -- choose interval
    select trunc(min(ts)) into minSince from message_part;
    select trunc(max(ts))+1 into maxSince from message_part;
    begin
        select max(source_date) + jobCount into since from message_fixup_log
        where finished_at is not null
              and mod(source_date - minSince, jobCount) = jobNumber
              and source_date >= minSince;
    exception when no_data_found then null;
    end;
    if (since is null) then
        since := minSince + jobNumber;
    end if;
    if (since >= maxSince) then
        if (jobName is not null) then
            dbms_scheduler.set_attribute(jobName, 'end_date', systimestamp + interval '1' second);
        end if;
        return;
    end if;

    insert into message_fixup_log(source_date, started_at) values(since, systimestamp);

    -- perform some actual work for chosen interval
    msgUpdatedCount := sql%rowcount;

    update message_fixup_log
    set fixed_message_count = msgUpdatedCount, finished_at = systimestamp
    where source_date = since;
end;

-- manual test
--call message_fixup(0, 1);

declare
    jobName varchar2(256);
    jobCount number default 8;
begin
    for jobNumber in 0..(jobCount-1) loop
        jobName := 'message_fixup_job' || jobNumber;
        begin
            dbms_scheduler.drop_job(jobName, true);
            exception
            when others then null;
        end;
        dbms_scheduler.create_job(
                job_name          => jobName,
                job_type          =>  'stored_procedure',
                job_action        =>  'message_fixup',
                enabled           =>  false,
                start_date        =>  systimestamp,
                repeat_interval   =>  'freq = minutely; interval = 1',
                number_of_arguments => 3
        );
        dbms_scheduler.set_attribute(jobName, 'logging_level', dbms_scheduler.logging_full);
        dbms_scheduler.set_job_anydata_value(jobName, 1, ANYDATA.ConvertNumber(jobNumber));
        dbms_scheduler.set_job_anydata_value(jobName, 2, ANYDATA.ConvertNumber(jobCount));
        dbms_scheduler.set_job_argument_value(jobName, 3, jobName);
        dbms_scheduler.enable(jobName);
    end loop;
end;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top