Oracle

為什麼 dbms_scheduler max_run_duration 不引發事件 JOB_OVER_MAX_DUR?

  • November 26, 2015

從這個問題和這個例子開始,我嘗試創建一個基於事件的dbms_scheduler作業,它等待JOB_OVER_MAX_DUR從作業引發的事件,這超出了他們的max_run_duration.

不幸的是,我無法讓該範例適用JOB_OVER_MAX_DUR 於 Oracle 10gR2中某個特定 box 上的事件。

我試過的是:

-- create log table
create table job_output (a timestamp with time zone, b varchar2(1000));

-- add an event queue subscriber for this user's messages
exec dbms_scheduler.add_event_queue_subscriber('myagent')

-- create a sniper procedure
create or replace procedure sniper_proc
 (message IN sys.scheduler$_event_info) as
begin
--
 insert into job_output values (systimestamp,'sniper job started for '
  ||message.event_type||' from '
  ||'"'||message.object_owner||'"."'||message.object_name ||'"');
 commit;
end;
/

-- create a sniper program
begin
 dbms_scheduler.create_program (
     program_name => 'sniper_prog',
     program_action=> 'sniper_proc',
     program_type => 'stored_procedure',
     number_of_arguments => 1,
     enabled => FALSE) ;
--
 dbms_scheduler.define_metadata_argument ('sniper_prog','event_message',1);
 dbms_scheduler.enable('sniper_prog');
end;
/

-- create a general purpose sniper job to log any job that has
-- raised an event
begin
 dbms_scheduler.create_job('sniper_job',
   program_name=>'sniper_prog',
   event_condition =>
     'tab.user_data.event_type = ''JOB_OVER_MAX_DUR'' OR tab.user_data.event_type = ''JOB_SUCCEEDED''',
   queue_spec =>'sys.scheduler$_event_queue,myagent',
   enabled=>true);
end;
/

-- create job to test the sniper job
begin
 dbms_scheduler.create_job
   ( 'first_job', job_action =>
       'insert into job_output values(systimestamp, ''first job begins'');
        commit; dbms_lock.sleep(120);
        insert into job_output values(systimestamp, ''first job ends'');',
     job_type => 'plsql_block',
     enabled => false ) ;
 -- set max runtime
 dbms_scheduler.set_attribute
   ( 'first_job' , 'max_run_duration' , interval '60' second);
 -- set all events to be raised (for debugging)
 dbms_scheduler.set_attribute(
   name      => 'first_job',
   attribute => 'raise_events',
   value     => dbms_scheduler.job_all_events);
 -- start the job
 dbms_scheduler.enable('first_job');  
end;
/

由於某種原因,該事件JOB_OVER_MAX_DUR要麼沒有被引發,要麼 sniper_job 沒有收到它。只JOB_SUCCEEDED收到。

我的日誌表如下所示:

SELECT *
 FROM job_output
ORDER BY 1 DESC;


25.07.2012 10:39:11,475879 +02:00   sniper job started for JOB_SUCCEEDED from "SCOTT"."FIRST_JOB"
25.07.2012 10:39:10,155557 +02:00   first job ends
25.07.2012 10:37:10,142660 +02:00   first job begins

所以沒有JOB_OVER_MAX_DUR收到任何事件。

任何想法我做錯了什麼或我必須檢查/設置哪些初始化參數或如何調試這些事件?

**編輯:**我很感興趣為什麼這在 10g 中不起作用。此範例在 11g 中執行良好,但在 10g 中執行良好,我看不出任何原因。

**編輯 2:**該範例在不同的 10g 盒子上執行良好,但在預期的盒子上卻不是。我已經檢查了所有的%scheduler%字典視圖,但沒有一個提供有關引發哪些事件的詳細資訊。任何想法/提示如何調試調度程序事件?在這種情況下,我擁有 DBA 權限和 OS 伺服器級別的調試權限。

添加多個屬性時,請嘗試:

DBMS_SCHEDULER.set_attribute(
   name      => 'first_job',
   attribute => 'raise_events',
   value     => DBMS_SCHEDULER.job_succeeded + DBMS_SCHEDULER.some_attribute);

事件類型 (11gr2) 的有效值在此處。根據文件,job_over_max_dur 已經為 11gr2 啟用。

現在,對於 10g 或11gr1,我在調度程序引發的事件類型列表中看不到 job_over_max_dur 。但是您在之前的文章中提到您將很快遷移到 11gr2,所以我假設您已經有一個測試盒設置,您可以使用 11gr2 進行測試。如果您真的想在 AQ 上陷入困境,您可以做更多的自定義事件,但等到 11gr2 之前可能會更容易。

編輯

要添加更多資訊,首先您可以查看一些基本的調度程序內容以查看正在執行的內容(或已調度、已停止或任何狀態):

select * from dba_scheduler_jobs
where owner = 'SOME_OWNER'
and job_name = 'SOME_JOB';

您可以查看是否設置了 max_run_duration 列,並且“raise_events”列將顯示每個作業要引發的事件類型列表。您應該在此處看到“JOB_OVER_MAX_DUR”類型。

如果您想測試您的數據庫環境是否正確處理 JOB_OVER_MAX_DUR,那麼您可以設置一個快速測試:

BEGIN
   -- setup simple scheduler job
  --DBMS_SCHEDULER.DROP_JOB('EVENT_RAISING_JOB',false);
  DBMS_SCHEDULER.create_job (
     job_name        => 'EVENT_RAISING_JOB',
     job_type        => 'PLSQL_BLOCK',
     job_action      => 'BEGIN
                           dbms_lock.sleep(70);
                         END;',
     start_date      => SYSTIMESTAMP,
     end_date        => SYSTIMESTAMP + 2, -- 2 day
     repeat_interval => 'freq=daily; byhour=1',
     enabled         => TRUE);

   DBMS_SCHEDULER.set_attribute(name=>'event_raising_job', attribute=>'max_run_duration', value=>interval '60' second);

  DBMS_SCHEDULER.set_attribute(name => 'event_raising_job', attribute => 'raise_events',value => DBMS_SCHEDULER.job_all_events );

END;

-- setup email notification
exec dbms_scheduler.add_job_email_notification( job_name=>'EVENT_RAISING_JOB',recipients=>'someuser@somedomain.com', events=>'job_all_events');

-- launch job
exec dbms_scheduler.run_job('EVENT_RAISING_JOB',false);

您應該收到 3 封電子郵件表明該工作:STARTED、SUCCEEDED 和 JOB_OVER_MAX_DUR

JOB_OVER_MAX_DUR 事件直到 11.2 才在文件中列出,即使 MAX_RUN_DURATION 在更早的版本中可用。

比較11.211.1

此外:

  • DBMS_SCHEDULER.JOB_ALL_EVENTS在 11.2 上不包括JOB_OVER_MAX_DUR(儘管名稱)。
  • 設置RAISE_EVENTS屬性既不會設置也不會刪除JOB_OVER_MAX_DUR事件。

似乎可以設置標誌的唯一方法是設置MAX_RUN_DURATION為非空值。相反,刪除它的唯一方法是將其設置MAX_RUN_DURATION為 null。

至於為什麼在 10.2 中甚至從未引發該事件,我懷疑該事件最初可能只是針對電子郵件通知實現的,而不是其他事件偵聽器。這似乎與我在 Oracle Support 上發現的一個錯誤有關(錯誤 #8792892);這意味著在工作鏈中使用事件的類似問題直到 11.2 才修復。

引用自:https://dba.stackexchange.com/questions/21540