2013-03-08 75 views
1

我我的包,我入隊多個作業是這樣的:如何等待所有調度程序作業完成?

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; 

如何才能阻止我的代碼,直到所有的工作完成?任何人都可以給我一個例子,如果有更好的方法來做到這一點?

+2

>我怎麼能等到我所有的調度工作已經完成? 打個盹; ^) – 2013-03-08 14:35:45

+4

看到這個[回答相似的問題](http://stackoverflow.com/a/4600487/119634),亞當霍克斯建議通過dbms_scheduler創建一個鏈。它看起來像一個優雅的解決方案 – 2013-03-08 14:52:59

+0

@VincentMalgrat,一個很好的資源。謝謝。它解決了這個問題。 – 2013-11-27 15:06:02

回答

1

不幸的是,Oracle中的會話間通信並不像OS中的進程間通信那麼方便。但是你可以

lock table ... in exclusive mode 

工作中,並用

select ... for update 
1

執行作業終止等待,如果你沒有很多的工作,你可以使用DBMS_LOCK包來創建自己的鎖定對象。用一些知名的名字爲每個作業創建一個。讓作業獲得鎖,並且主作業等待所有鎖被釋放。

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; 
+0

歡迎來到SO。你能解釋一下,爲什麼這能解決OP問題? – m00am 2016-02-25 10:05:56