2

我是我的包裹,我正在排队多个这样的工作:

dbms_scheduler.create_job
  ( job_name     => p_job_name
  , job_type     => 'PLSQL_BLOCK'
  , job_action   => p_sql_code
  , start_date   => SYSDATE
  , enabled      => TRUE
  , comments     => 'Running batch jobs in parallel');

一旦我为希望开始的许多并行作业完成了此操作,我需要阻止,直到所有作业都完成。

目前我不得不睡觉并轮询表格ALL_SCHEDULER_JOB_RUN_DETAILSALL_SCHEDULER_JOBS检查工作的状态。这似乎是一个非常丑陋的解决方案。这是我使用的 SQL:

PROCEDURE run_jobs
  ( p_jobs    StringTableType
  , p_sql     VARCHAR2(4000) )
IS

  l_jobs         StringTableType;
  l_status       sys_type.STRING;
  l_additional_info  sys_type.text;
  l_done         BOOLEAN;
  i              PLS_INTEGER;

BEGIN

  l_jobs := p_jobs;

  -- Submit jobs
  FOR i IN 1..l_jobs.COUNT LOOP

  dbms_scheduler.create_job
    ( job_name     => l_jobs(i)
    , job_type     => 'PLSQL_BLOCK'
    , job_action   => p_sql
    , start_date   => SYSDATE
    , enabled      => TRUE
    , comments     => 'Running batch jobs in parallel');

  END LOOP;

  -- now wait untile all jobs are finished
  l_done := FALSE;

  WHILE NOT l_done LOOP

    DBMS_LOCK.sleep(5);

    l_done := TRUE;

    i := l_jobs.FIRST;
    WHILE i IS NOT NULL LOOP

      WITH jobs_log
           AS (SELECT job_name, state status, '' additional_info
                 FROM all_scheduler_jobs
               UNION
               SELECT job_name, status, additional_info
                 FROM all_scheduler_job_run_details
               )
      SELECT status, additional_info
        INTO l_status, l_additional_info
        FROM jobs_log
       WHERE job_name = p_jobs (i);

      --Analyze job status
      CASE
        WHEN l_status = 'RUNNING' THEN
          l_done := FALSE;

        WHEN l_status = 'SUCCEEDED' THEN
          l_jobs.DELETE(i);

        WHEN l_status = 'FAILED' THEN
          l_jobs.DELETE(i);

        ELSE
          l_done := FALSE;

      END CASE;

      i := l_jobs.NEXT(i);

    END LOOP;

  END LOOP;

END run_jobs;

在所有作业完成之前,如何阻止我的代码?如果有更好的方法,谁能给我一个例子?

4

4 回答 4

2

当有人发布来自另一个 StackOverflow 答案的链接时,这可以使用来自DBMS_SCHEDULER.

等待提交的作业在 Oracle PL/SQL 中完成?

于 2013-11-27T15:05:22.607 回答
1

不幸的是,Oracle 中的会话间通信不如 OS 中的进程间通信方便。但是你可以

lock table ... in exclusive mode

在工作中并通过以下方式执行工作终止等待

select ... for update
于 2013-03-08T15:10:51.870 回答
1

如果你没有很多工作,你可以使用 DBMS_LOCK 包来创建你自己的锁对象。使用一些知名名称为每个作业创建一个。让作业获取锁,主作业等待所有要释放的锁。

于 2013-03-11T01:23:49.113 回答
1
DECLARE
  cnt NUMBER:=1;
BEGIN
  WHILE cnt>=1
  LOOP
    SELECT count(1) INTO cnt FROM dba_scheduler_running_jobs srj
    WHERE srj.job_name IN ('TEST_JOB1','TEST_JOB2');
    IF cnt>0 THEN
      dbms_lock.sleep (5);
    END IF;
  END LOOP;
  dbms_output.put_line('ASASA');  
END;
于 2016-02-25T09:45:31.697 回答