Распараллеливание вызовов в 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
, вам нужно передать второй параметр. Theuse_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
)