国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數(shù)據(jù)庫 > Oracle > 正文

Oracle作業(yè)(JOB)更新next_date的探討

2024-08-29 13:29:32
字體:
供稿:網(wǎng)友

oracle作業(yè)(job)更新next_date的探討

 

本文作者:kamus([email protected])

 

摘要:本文通過實驗和事件跟蹤來分析oracle job執(zhí)行過程中修改下次執(zhí)行時間的機制。

 

有些人問,oracle的job在設(shè)定完next_date和interval之后,到底是什么時候決定下一次運行時間的??梢詺w納成以下幾個問題。

1. 假設(shè)我們的job設(shè)定第一次運行的時間是12:00,運行的間隔是1小時,job運行需要耗時30分鐘,那么第二次運行是在13:00還是13:30?

2. 如果是在13:00那是不是說明只要job一開始運行,next_date就被重新計算了?

3. job的下一次運行會受到上一次運行時間的影響嗎?如果受到影響,如何可以避免這個影響而讓job在每天的指定時刻運行?

 

本文通過一些實驗和跟蹤來解釋上面的所有問題。

 

首先我們選擇一個測試用戶,假設(shè)該用戶名為kamus。

由于我們在實驗用的存儲過程中會用到dbms_lock包,所以需要由sys用戶先授予kamus用戶使用dbms_lock包的權(quán)限。

 

d:/temp>sqlplus "/ as sysdba"

 

sql*plus: release 9.2.0.5.0 - production on 星期三 12月 1 23:56:32 2004

 

copyright (c) 1982, 2002, oracle corporation.  all rights reserved.

 

 

連接到:

oracle9i enterprise edition release 9.2.0.5.0 - production

with the partitioning, olap and oracle data mining options

jserver release 9.2.0.5.0 - production

 

sql> grant execute on dbms_lock to kamus;

 

授權(quán)成功。

 

然后用kamus用戶登錄數(shù)據(jù)庫,創(chuàng)建我們測試使用的存儲過程sp_test_next_date。

 

create or replace procedure sp_test_next_date as
  p_jobno    number;
  p_nextdate date;
begin
  --將調(diào)用此存儲過程的job的next_date設(shè)置為30分鐘以后
  select job into p_jobno from user_jobs where what = 'sp_test_next_date;';
  execute immediate 'begin dbms_job.next_date(' || to_char(p_jobno) || ',sysdate+1/48);commit;end;';
  --修改完畢以后檢查user_jobs視圖,輸出job目前的next_date
  select next_date
    into p_nextdate
    from user_jobs
   where what = 'sp_test_next_date;';
  dbms_output.put_line('job執(zhí)行中的next_date: ' ||
                       to_char(p_nextdate,'yyyy-mm-dd hh24:mi:ss'));
  --等待10秒再退出執(zhí)行
  dbms_lock.sleep(seconds => 10);
end sp_test_next_date;

 

創(chuàng)建調(diào)用該存儲過程的job,定義interval為每天一次,也就是這次執(zhí)行以后,下次執(zhí)行時間應(yīng)該在1天以后。

 

sql> variable jobno number;

sql> begin

  2  dbms_job.submit(job => :jobno,

  3  what => 'sp_test_next_date;',

  4  next_date => sysdate,

  5  interval => 'sysdate+1');

  6  commit;

  7  end;

  8  /

 

pl/sql 過程已成功完成。

 

jobno

---------

1

 

然后我們手工執(zhí)行存儲過程,執(zhí)行完畢以后再手工從user_jobs視圖中獲得job的下次執(zhí)行時間,可以看到在存儲過程中修改的job的下次執(zhí)行時間已經(jīng)生效,變成了當(dāng)前時間的30分鐘以后,而不是默認(rèn)的1天以后。

 

sql> conn kamus

請輸入口令:

已連接。

sql> set serverout on

sql> exec sp_test_next_date();

job執(zhí)行中的next_date: 2004-12-02 00:44:11

 

pl/sql 過程已成功完成。

 

sql> col next_date for a20

sql> select to_char(next_date,'yyyy-mm-dd hh24:mi:ss') next_date from user_jobs

where what = 'sp_test_next_date;';

 

next_date

--------------------

2004-12-02 00:44:11

 

我們再手工運行job,看看這次的結(jié)果,可以發(fā)現(xiàn)job沒有運行完畢以前被修改了的下次運行時間跟job運行完畢以后再次手工檢索user_jobs視圖獲得的下次運行時間已經(jīng)不相同了。由此我們可以得出一個結(jié)論,next_date是在job運行完畢以后被oracle自動修改的,而不是在job剛開始運行的時候,因為我們在存儲過程中修改的next_date在job運行結(jié)束之后又被修改為默認(rèn)的1天以后了。

 

sql> exec dbms_job.run(1);

job執(zhí)行中的next_date: 2004-12-02 00:54:52

 

pl/sql 過程已成功完成。

 

sql> select to_char(next_date,'yyyy-mm-dd hh24:mi:ss') next_date from user_jobs

where what = 'sp_test_next_date;';

 

next_date

--------------------

2004-12-03 00:24:52

 

現(xiàn)在我們再次修改存儲過程,輸出存儲過程開始執(zhí)行的時間,便于跟執(zhí)行完畢以后的job下次執(zhí)行時間進行比較。

 

create or replace procedure sp_test_next_date as
  p_jobno    number;
  p_nextdate date;
begin
  --輸出job剛開始執(zhí)行的時間
  dbms_output.put_line(' job開始執(zhí)行的時間: ' ||
                       to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'));
  --將調(diào)用此存儲過程的job的next_date設(shè)置為30分鐘以后
  select job into p_jobno from user_jobs where what = 'sp_test_next_date;';
  execute immediate 'begin dbms_job.next_date(' || to_char(p_jobno) || ',sysdate+1/48);commit;end;';
  --修改完畢以后檢查user_jobs視圖,輸出job目前的next_date
  select next_date
    into p_nextdate
    from user_jobs
   where what = 'sp_test_next_date;';
  dbms_output.put_line(' job執(zhí)行中的next_date: ' ||
                       to_char(p_nextdate,'yyyy-mm-dd hh24:mi:ss'));
  --等待10秒再退出執(zhí)行
  dbms_lock.sleep(seconds => 10);
end sp_test_next_date;

 

重新進行測試,我們可以發(fā)現(xiàn)job的next_date是job開始執(zhí)行時間的1天以后,而不是job結(jié)束時間的1天以后(因為job結(jié)束需要經(jīng)過10秒鐘)

 

sql> exec dbms_job.run(1);

job開始執(zhí)行的時間: 2004-12-02 00:38:24

job執(zhí)行中的next_date: 2004-12-02 01:08:24

 

pl/sql 過程已成功完成。

 

sql> select to_char(next_date,'yyyy-mm-dd hh24:mi:ss') next_date from user_jobs

where what = 'sp_test_next_date;';

 

next_date

--------------------

2004-12-03 00:38:24

 

至此,我們已經(jīng)說明了兩個問題。就是:job在運行結(jié)束之后才會更新next_date,但是計算的方法是job剛開始的時間加上interval設(shè)定的間隔。

 

下面我們通過trace來再次求證這個結(jié)論。

sql> alter session set events '10046 trace name context forever, level 12';

 

會話已更改。

 

sql> exec dbms_job.run(1);

 

pl/sql 過程已成功完成。

 

sql> alter session set events '10046 trace name context off';

 

會話已更改。

 

執(zhí)行完畢以后在udump目錄中查看生成的trace文件。如果我們用tkprof來格式化這個trace文件然后再查看格式化后的結(jié)果,我們會感到很詫異。因為在格式化完畢的sql執(zhí)行順序中,更新job$表的語句出現(xiàn)在dbms_job.next_date語句之前,也就是看上去是oracle先按照interval自動更新了job的next_date,然后才繼續(xù)往下執(zhí)行存儲過程中定義的next_date更新語句,而這樣顯然無法解釋我們在上面的實驗中看到的結(jié)果。

但是當(dāng)我們跳過tkprof而直接去查看生成的trace文件,就會恍然大悟,同時也印證了steve adams在ixora上提到的觀點:tkprof格式化完的結(jié)果會省略一些信息,甚至在有時候會給我們錯誤的信息。

直接查看trace文件,我們可以看到如下的執(zhí)行順序:

1. parse cursor #10(oracle根據(jù)interval和先前保存的this_date字段值更新job$表的語句,包括更新failures, last_date, next_date, total等)

2. parse cursor #15(存儲過程中的begin dbms_job.next_date語句)

3. binds cursor #15(將加上了30分鐘的時間綁定到cursor #15上)

4. exec cursor #15(執(zhí)行cursor #15)

5. wait cursor #11(經(jīng)歷一個pl/sql lock timer事件,也就是存儲過程中執(zhí)行的dbms_lock.sleep方法)

6. binds cursor #10(將job剛開始執(zhí)行時候的時間綁定到cursor #10上)

7. exec cursor #10(執(zhí)行cursor #10)

 

也就是說雖然更新job$的語句被很早地解析過了,但是直到j(luò)ob運行結(jié)束時這個被解析過的游標(biāo)才開始作變量綁定進而開始執(zhí)行。

正是因為解析update sys.job$語句的時間早于解析begin dbms_job.next_date語句的時間,所以tkprof的結(jié)果將前者放在了前面。

由于trace文件過長,所以不在本文中貼出了,如果有興趣可以發(fā)郵件給我。我的郵件地址是:[email protected]

 

本文的最后一部分,解答本文開頭提出的第三個問題,也就是:

job的下一次運行會受到上一次運行時間的影響嗎?如果受到影響,如何可以避免這個影響而讓job在每天的指定時刻運行?

job的下一次運行時間是會受上一次影響的,如果我們的interval僅僅是sysdate+1/24這樣的形式的話,無疑,上次執(zhí)行的時間再加上1小時就是下次執(zhí)行的時間。那么如果job因為某些原因延遲執(zhí)行了一次,這樣就會導(dǎo)致下一次的執(zhí)行時間也同樣順延了,這通常不是我們希望出現(xiàn)的現(xiàn)象。

解決方法很簡單,只需要設(shè)定正確的interval就可以了。

比如,我們要job在每天的凌晨3:30執(zhí)行而不管上次執(zhí)行到底是幾點,只需要設(shè)置interval為trunc(sysdate)+3.5/24+1即可。完整的sql如下:

sql> variable jobno number;

sql> begin

  2  dbms_job.submit(job => :jobno,

  3  what => 'sp_test_next_date;',

  4  next_date => sysdate,

  5  interval => 'trunc(sysdate)+3.5/24+1');

  6  commit;

  7  end;

  8  /

 

btw:在trace文件中發(fā)現(xiàn)雖然通過select rowid from table返回的結(jié)果已經(jīng)是擴展rowid格式(data object number + file + block + row)了,但是oracle內(nèi)部檢索數(shù)據(jù)仍然在使用限制rowid格式(block number.row number.file number)。

 

本文涉及到的額外知識可以參看我的其它技術(shù)文章:

1. 通過事件跟蹤sql執(zhí)行的后臺步驟

2. oracle等待事件,比如本文提到的pl/sql lock timer

3. rowid格式

 

作者簡介:

張樂奕,網(wǎng)名kamus

曾任itpub oracle認(rèn)證版版主,現(xiàn)任itpub oracle管理版版主.  

現(xiàn)任職于北京某大型軟件公司,首席dba,主要負(fù)責(zé)證券行業(yè)的全國十?dāng)?shù)處核心交易系統(tǒng)數(shù)據(jù)庫管理及維護工作。

熱切關(guān)注oracle技術(shù)和其它相關(guān)技術(shù),出沒于各大數(shù)據(jù)庫技術(shù)論壇,目前是中國最大的oracle技術(shù)論壇www.itpub.net的數(shù)據(jù)庫管理版版主,

閱讀更多技術(shù)文章和隨筆可以登錄我的個人blog。
http://blog.cdsn.net/kamus。

 
注冊會員,創(chuàng)建你的web開發(fā)資料庫,
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 交城县| 无极县| 马鞍山市| 宣武区| 临湘市| 左权县| 民权县| 洞口县| 大连市| 西畴县| 崇仁县| 板桥市| 临湘市| 英德市| 久治县| 常山县| 武平县| 伊川县| 河南省| 新兴县| 临高县| 石棉县| 安陆市| 东丽区| 莱州市| 深水埗区| 广宗县| 祁门县| 陆河县| 新河县| 通渭县| 曲松县| 体育| 车险| 乃东县| 宿松县| 清丰县| 阳信县| 镇雄县| 竹北市| 江阴市|