Распараллеливание вызовов в PL / SQL

у меня есть пакет с proc, который будет выполнять ряд других процедур, например:

CREATE PACKAGE BODY pkg IS
    CREATE PROCEDURE do
    IS
    BEGIN
        other_pkg.other_proc;
        other_pkg2.other_proc2;
        other_pkg3.other_proc3;
    END;
END;

есть ли способ заставить процедуры выполняться параллельно, а не последовательно?

EDIT:

это правильный способ использовать DBMS_SCHEDULER в данном случае:

CREATE PACKAGE BODY pkg IS
    CREATE PROCEDURE do
    IS
    BEGIN
        DBMS_SCHEDULER.CREATE_JOB('job_other_pkg.other_proc', 'STORED_PROCEDURE', 'other_pkg.other_proc;');
        DBMS_SCHEDULER.RUN_JOB('job_other_pkg.other_proc', FALSE);
        -- ...
    END;
END;

2 ответов


можно использовать dbms_job (или dbms_scheduler пакет) для отправки заданий, которые будут выполняться параллельно. Если вы используете dbms_job, отправка заданий будет частью транзакции, поэтому задания будут запускаться после завершения транзакции.

CREATE PACKAGE BODY pkg IS
    CREATE PROCEDURE do
    IS
      l_jobno pls_integer;
    BEGIN
        dbms_job.submit(l_jobno, 'begin other_pkg.other_proc; end;' );
        dbms_job.submit(l_jobno, 'begin other_pkg2.other_proc2; end;' );
        dbms_job.submit(l_jobno, 'begin other_pkg3.other_proc3; end;' );
    END;
END;

если вы используете dbms_scheduler, создание нового задания не является транзакционным (т. е. будут неявные коммиты каждый раз, когда вы создали новое задание), что может вызвать проблемы с транзакционной целостностью, если в транзакция, в которой вызывается эта процедура. С другой стороны, если вы используете dbms_scheduler, может быть проще создать задания заранее и просто запустить их из процедуры (или использовать dbms_scheduler чтобы создать цепочку, которая запускает задание в ответ на какое-либо другое действие или событие, например, размещение сообщения в очереди).

конечно, с любым решением вам нужно будет затем построить инфраструктуру для мониторинга прогресса этих трех заданий, предполагая, что вам все равно, когда и будут ли они успешно (и порождают ли они ошибки).

если вы собираетесь использовать DBMS_SCHEDULER

  • нет необходимости использовать динамический SQL. Вы можете бросить EXECUTE IMMEDIATE и просто позвонить DBMS_SCHEDULER процедуры пакета сразу как раз как вы любая другая процедура.
  • когда вы называете RUN_JOB, вам нужно передать второй параметр. The use_current_session параметр определяет, выполняется ли задание в текущем сеансе (и блоках) или выполняется в отдельном сессия (в этом случае текущая сессия может продолжаться и делать другие вещи). Поскольку вы хотите запускать несколько заданий параллельно, вам нужно будет передать значение false.
  • хотя это не требуется, было бы более обычным, чтобы создать рабочие места один раз (с auto_drop установите значение false), а затем просто запустите их из своей процедуры.

поэтому вы, вероятно, захотите создать задания вне пакета, а затем ваша процедура будет просто стать

CREATE PACKAGE BODY pkg IS
    CREATE PROCEDURE do
    IS
    BEGIN
        DBMS_SCHEDULER.RUN_JOB('job_other_pkg.other_proc', false);
        DBMS_SCHEDULER.RUN_JOB('job_other_pkg2.other_proc2', false);
        DBMS_SCHEDULER.RUN_JOB('job_other_pkg3.other_proc3', false);
    END;
END;

другое решение -взломать механизм параллелизма SQL Oracle. Ответ для Как выполнить хранимую процедуру в другом сеансе в то же время в pl/sql .

он использует большое решение Уильяма Робертсона параллельный PL / SQL launcher.

(проверено с Oracle 10g)