我有一个包含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;
有没有办法让程序并行而不是串行执行?
编辑:
这是在这种情况下使用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;
答案 0 :(得分:8)
您可以使用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
EXECUTE IMMEDIATE
并直接调用DBMS_SCHEDULER
包的程序,就像您执行任何其他程序一样。RUN_JOB
时,您需要传入第二个参数。 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;
答案 1 :(得分:1)
另一个解决方案是破解Oracle的SQL并行机制。请参阅How to execute a stored procedure in a different session in same time in pl/sql的答案。
它使用William Robertson的出色解决方案Parallel PL/SQL launcher。
(使用Oracle 10g
测试)