如何在pl / sql中同时在不同会话中执行存储过程

Posted

技术标签:

【中文标题】如何在pl / sql中同时在不同会话中执行存储过程【英文标题】:How to execute a stored procedure in a different session in same time in pl/sql 【发布时间】:2016-05-12 06:01:58 【问题描述】:

PL/SQL 中是否有可能调用多个会话并同时在多个会话中运行一个过程。

我想在有 250 个用户登录应用程序的实时应用程序中使用它。用户通过客户端工具连接到 Oracle。 (Power Builder 是前端工具)

例如,如果用户调用存储过程,则该存储过程必须使用不同的参数值运行 10 次。 我不想在同一个会话中依次运行 10 次,因为这可能需要很长时间。 我正在寻找一种可以同时在 10 个不同会话中运行存储过程的方法。

我曾考虑使用 DBMS_JOB.SUBMIT 放置 10 个作业,但因为 繁重的工作负载(250 个用户 * 10 = 2500 个工作可能同时在 Job 调度器中调度,依此类推)我们的 DBA 小组正在寻找其他更好的方法。

【问题讨论】:

Run/execute multiple procedures in Paralel oracle的可能重复 既然你说你有很多用户想要运行这个过程,你应该首先检查你的数据库是否可以处理那么多并行执行。每个同时运行的内核大约有一个存储过程(可能更多一些)是您将获得的最好的。如果您有一个并发用户执行存储过程,等待时间是多少? 【参考方案1】:

为避免发布多个 Oracle 职位,您可以尝试使用 William Robertson Parallel PL/SQL launcher

如果您创建一个表“PQ_DRIVER”,它有 4 个分区,并行度为 4,每个分区有一行,并且您按照“SELECT /*+ PARALLEL(pq,4) */ thread_id FROM pq_driver pq”的行执行查询,这应该会说服 PQ控制器设置四个 PQ 从进程来处理它(每个分区一个)。如果您将该查询作为游标参数传递给启用并行的流水线函数,那么这不应该造成每一行都由单独的 PQ 从进程处理的情况吗?因此,这是一种使用(好吧,破解)PQ 引擎的方法,以便它并行处理任意 PL/SQL 过程调用。

这个想法是使用 PARALLEL_ENABLEPIPELINED 功能创建一个函数:

   function pq_submit
    ( p_job_list  varchar2_tt
    , p_pq_refcur rc_pq_driver )
    return varchar2_tt
    parallel_enable(partition p_pq_refcur by any)
    pipelined
 is
 ...
 loop
   execute_command(your_proc);
 end loop;

函数execute_command 使用autonomous_transaction

看起来像这样:

procedure execute_command
  ( p_what log_times.what%type )
is
  pragma autonomous_transaction;
begin
  execute immediate p_what;
  commit;
end execute_command;

【讨论】:

【参考方案2】:

除了创建JOBs,您还可以使用DBMS_PARALLEL_EXECUTE package。

这里有一些点击:

使用 create_chunks_by_sqlby_rowid => FALSE,即使用 ID 并创建与执行存储过程所需的完全相同数量的块。

run_task 中,将parallel_level 设置为所需的并行度。如果您需要限制并行度,则此数字与上述相同或更低。

通过调用 过程作为参数sql_stmt 例如

BEGIN
  test_proc(:start_id,:end_id);
END;

您可以选择将块编号传递给过程,因此您可以将其用作threadId

这里有一个完整的例子

创建任务和 3 个块

DECLARE
  l_stmt CLOB;
BEGIN
  DBMS_PARALLEL_EXECUTE.create_task (task_name => 'parallel PL/SQL');

  l_stmt := 'SELECT rownum, rownum FROM dual connect by level <= 3';

  DBMS_PARALLEL_EXECUTE.create_chunks_by_sql(task_name => 'parallel PL/SQL',
                                             sql_stmt  => l_stmt,
                                             by_rowid  => FALSE);
END;
/

使用 DOP = 3 运行任务

DECLARE
  l_sql_stmt VARCHAR2(32767);
BEGIN
  l_sql_stmt := 'BEGIN
                   test_proc(:start_id,:end_id);
                END;';   

  DBMS_PARALLEL_EXECUTE.run_task(task_name      => 'parallel PL/SQL',
                                 sql_stmt       => l_sql_stmt,
                                 language_flag  => DBMS_SQL.NATIVE,
                                 parallel_level => 3);
END;
/

删除任务

BEGIN
  DBMS_PARALLEL_EXECUTE.drop_task('parallel PL/SQL');
END;
/

【讨论】:

以上是关于如何在pl / sql中同时在不同会话中执行存储过程的主要内容,如果未能解决你的问题,请参考以下文章

如何以不同的方式处理 PL/SQL 中的不同异常?

oracle存储过程连续执行结果不同

如何在 Oracle PL/SQL 中执行存储函数

执行存储过程 - Oracle PL SQL

PL_sql如何执行oracle存储过程

怎样在pl/sql中创建,执行和删除存储过程