久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Oracle job定時任務怎么理解

165次閱讀
沒有評論

共計 10436 個字符,預計需要花費 27 分鐘才能閱讀完成。

這篇文章主要介紹“Oracle job 定時任務怎么理解”,在日常操作中,相信很多人在 Oracle job 定時任務怎么理解問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Oracle job 定時任務怎么理解”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!

Oracle job 定時任務

任務隊列要能正常運行,還必須啟動它自己專有的后臺過程,參數如下:
JOB_QUEUE_PROCESSES = n

這個是運行 JOB 時候所起的進程數,當然系統里面 JOB 大于這個數值后,就會有排隊等候的,最小值是 0,表示不運行 JOB,最大值是 1000,在 OS 上對應的進程時 SNPn,9i 以后 OS 上管理 JOB 的進程叫 CJQn。
可以使用下面這個 SQL 確定目前有幾個 SNP/CJQ 在運行。
SQL set lines 200
SQL select * from v$bgprocess where name like CJQ%

PADDR  PSERIAL# NAME  DESCRIPTION  ERROR
—————- ———- —– —————————————————————- ———-
C0000005F4610F38  1 CJQ0  Job Queue Coordinator  ##########

這個 paddr 不為空的 snp/cjq 進程就是目前空閑的進程,有的表示正在工作的進程。
 
三、DBMS_JOB 包參數
DBMS_JOB 包中所有的過程都有一組相同的公共參數,用于定義任務,任務的運行時間以及任務定時運行的時間間隔。這些公共任務定義參數見表 2 所示。
 
下面我們來詳細討論這些參數的意義及用法。

1、job
參數 job 是一個整數,用來唯一地標示一個任務。該參數既可由用戶指定也可由系統自動賦予,這完全取決于提交任務時選用了哪一個任務提交過程。DBMS_JOB.SUBMIT 過程通過獲得序列 SYS.JOBSEQ 的下一個值來自動賦予一個任務號。該任務號是作為一個 OUT 參數返回的,所以調用者隨后可以識別出提交的任務。而 DBMS_JOB.ISUBMIT 過程則由調用者給任務指定一個識別號,這時候,任務號的唯一性就完全取決于調用者了。

除了刪除或者重新提交任務,一般來說任務號是不能改變的。即使當數據庫被導出或者被導入這樣極端的情況,任務號也將被保留下來。所以在執行含有任務的數據的導入 / 導出操作時很可能會發生任務號沖突的現象。

2、what
what 參數是一個可以轉化為合法 PL/SQL 調用的字符串,該調用將被任務隊列自動執行。在 what 參數中,如果使用文字字符串,則該字符串必須用單引號括起來。what 參數也可以使用包含我們所需要字符串值的 VARCHAR2 變量。實際的 PL/SQL 調用必須用分號隔開。在 PL/SQL 調用中如果要嵌入文字字符串,則必須使用兩個單引號。

what 參數的長度在 Oracle7.3 中限制在 2000 個字節以內,在 Oracle 8.0 以后,擴大到了 4000 個字節,這對于一般的應用已完全足夠。該參數的值一般情況下都是對一個 PL/SQL 存儲過程的調用。在實際應用中,盡管可以使用大匿名 Pl/SQL 塊,但建議大家最好不要這樣使用。還有一個實際經驗就是最好將存儲過程調用封裝在一個匿名塊中,這樣可以避免一些比較莫名錯誤的產生。我來舉一個例子,一般情況下,what 參數可以這樣引用:
 
what =’my_procedure(parameter1);’
 
但是比較安全的引用,應該這樣寫:

what =’begin my_procedure(parameter1); end;’

任何時候,我們只要通過更改 what 參數就可以達到更改任務定義的目的。但是有一點需要注意,通過改變 what 參數來改變任務定義時,用戶當前的會話設置也被記錄下來并成為任務運行環境的一部分。如果當前會話設置和最初提交任務時的會話設置不同,就有可能改變任務的運行行為。意識到這個潛在的副作用是非常重要的,無論何時只要應用到任何 DBMS_JOB 過程中的 what 參數時就一定要確保會話設置的正確。

3、next_date
Next_date 參數是用來調度任務隊列中該任務下一次運行的時間。這個參數對于 DBMS_JOB.SUBMIT 和 DBMS_JOB.BROKEN 這兩個過程缺省為系統當前時間,也就是說任務將立即運行。

當將一個任務的 next_date 參數賦值為 null 時,則該任務下一次運行的時間將被指定為 4000 年 1 月 1 日,也就是說該任務將永遠不再運行。在大多數情況下,這可能是我們不愿意看到的情形。但是,換一個角度來考慮,如果想在任務隊列中保留該任務而又不想讓其運行,將 next_date 設置為 null 卻是一個非常簡單的辦法。

Next_date 也可以設置為過去的一個時間。這里要注意,系統任務的執行順序是根據它們下一次的執行時間來確定的,于是將 next_date 參數設置回去就可以達到將該任務排在任務隊列前面的目的。這在任務隊列進程不能跟上將要執行的任務并且一個特定的任務需要盡快執行時是非常有用的。

4、Interval
Internal 參數是一個表示 Oracle 合法日期表達式的字符串。這個日期字符串的值在每次任務被執行時算出,算出的日期表達式有兩種可能,要么是未來的一個時間,要么就是 null。這里要強調一點:很多開發者都沒有意識到 next_date 是在一個任務開始時算出的,而不是在任務成功完成時算出的。
當任務成功完成時,系統通過更新任務隊列目錄表將前面算出的 next_date 值置為下一次任務要運行的時間。當由 interval 表達式算出 next_date 是 null 時,任務自動從任務隊列中移出,不會再繼續執行。因此,如果傳遞一個 null 值給 interval 參數,則該任務僅僅執行一次。
通過給 interval 參數賦各種不同的值,可以設計出復雜運行時間計劃的任務。本文后面的“任務間隔和日期算法”將對 interval 表達式進行詳細討論,并給出一個實際有用 interval 表達式的例子。

四、任務隊列架構和運行環境

當 CJQn 進程喚醒時,它首先查看任務隊列目錄中所有的任務是否當前的時間超過了下一次運行的日期時間。CJQn 進程檢測到需要該時間立即執行的任務后,這些任務按照下一次執行日期的順序依次執行。當 CJQn 進程開始執行一個任務時,其過程如下:
1. 以任務所有者的用戶名開始一個新的數據庫會話。
2. 當任務第一次提交或是最后一次被修改時,更改會話 NLS 設置和目前就緒的任務相匹配。
3. 通過 interval 日期表達式和系統時間,計算下一次執行時間。
4. 執行任務定義的 PL/SQL
5. 如果運行成功,任務的下一次執行日期(next_date)被更新,否則,失敗計數加 1。
6. 經過 JOB_QUEUS_INTERVAL 秒后,又到了另一個任務的運行時間,重復上面的過程。

在前兩步中,CJQn 進程創建了一個模仿用戶運行任務定義的 PL/SQL 的會話環境。然而,這個模仿的運行環境并不是和用戶實際會話環境完全一樣,需要注意以下兩點:
第一,在任務提交時任何可用的非確省角色都將在任務運行環境中不可用。因此,那些想從非確省角色中取得權限的任務不能提交,用戶確省角色的修改可以通過在任務未來運行期間動態修改來完成。
第二,任何任務定義本身或者過程執行中需要的數據庫聯接都必須完全滿足遠程的用戶名和密碼。CJQn 進程不能在沒有顯式指明口令的情況下初始化一個遠程會話。顯然,CJQn 進程不能假定將本地用戶的口令作為遠程運行環境會話設置的一部分。

當任務運行失敗時,CJQn 進程在 1 分鐘后將再次試圖運行該任務。如果這次運行又失敗了,下一次嘗試將在 2 分鐘后進行,再下一次在 4 分鐘以后。任務隊列每次加倍重試間隔直到它超過了正常的運行間隔。在連續 16 次失敗后,任務就被標記為中斷的(broken),如果沒有用戶干預,任務隊列將不再重復執行。

五、任務隊列字典表和視圖
任務隊列中的任務信息可以通過表 3 所示的幾個字典視圖來查看,這些視圖是由 CATJOBQ.sql 腳本創建的。表 4 和 5 是各個視圖每個字段的含義。

六、任務重復運行間隔設計算法
任務重復運行的時間間隔取決于 interval 參數中設置的日期表達式。下面就來詳細談談該如何設置 interval 參數才能準確滿足我們的任務需求。一般來講,對于一個任務的定時執行,有三種定時要求。
1. 在一個特定的時間間隔后,重復運行該任務。
2. 在特定的日期和時間運行任務。
3. 任務成功完成后,下一次執行應該在一個特定的時間間隔之后。

第一種調度任務需求的日期算法比較簡單,即 SYSDATE+n , 這里 n 是一個以天為單位的時間間隔。表 6 給出了一些這種時間間隔設置的例子。

 
表 6 所示的任務間隔表達式不能保證任務的下一次運行時間在一個特定的日期或者時間,僅僅能夠指定一個任務兩次運行之間的時間間隔。
例如,如果一個任務第一次運行是在凌晨 12 點,interval 指定為 SYSDATE + 1 , 則該任務將被計劃在第二天的凌晨 12 點執行。但是,如果某用戶在下午 4 點手工(DBMS_JOB.RUN)執行了該任務,那么該任務將被重新定時到第二天的下午 4 點。還有一個可能的原因是如果數據庫關閉或者說任務隊列非常的忙以至于任務不能在計劃的那個時間點準時執行。在這種情況下,任務將試圖盡快運行,也就是說只要數據庫一打開或者是任務隊列不忙就開始執行,但是這時,運行時間已經從原來的提交時間漂移到了后來真正的運行時間。這種下一次運行時間的不斷“漂移”是采用簡單時間間隔表達式的典型特征。

第二種調度任務需求相對于第一種就需要更復雜的時間間隔(interval)表達式,表 7 是一些要求在特定的時間運行任務的 interval 設置例子。

 
第三種調度任務需求無論通過怎樣設置 interval 日期表達式也不能滿足要求。這時因為一個任務的下一次運行時間在任務開始時才計算,而在此時是不知道任務在何時結束的。

遇到這種情況怎么辦呢?當然辦法肯定是有的,我們可以通過為任務隊列寫過程的辦法來實現。這里我只是簡單介紹以下,可以在前一個任務隊列執行的過程中,取得任務完成的系統時間,然后加上指定的時間間隔,拿這個時間來控制下一個要執行的任務。這里有一個前提條件,就是目前運行的任務本身必須要嚴格遵守自己的時間計劃。

六、實驗概述
目前,流行的主流數據庫都擁有此項功能,最具代表性的是 Microsoft SQL Server 7.0、Oracle8i/9i 等。但是,要讓 Job 工作,還需要我們加以配置才能實現。這些配置都有 GUI 操作。本文介紹 Oracle9i 之后通過命令行實現 Job 配置 ……

眾所周知,一般操作系統會提供定時執行任務的方法,例如:Unix 平臺上提供了讓系統定時執行任務的命令 Crontab。但是,對于某些需求,例如:一些對數據庫表的操作,最為典型的是證券交易所每日收盤后的結算,它涉及大量的數據庫表操作,如果仍然利用操作系統去定時執行,不僅需要大量的編程工作,而且還會出現用戶不一致等運行錯誤,甚至導致程序無法執行。

事實上,對于以上需求,我們可以利用數據庫本身擁有的功能 Job Queue(任務隊列管理器)去實現。Job 允許用戶提前調度和安排某一任務,使其能在指定的時間點或時間段內自動執行一次或多次,由于任務在數據庫中被執行,所以執行效率很高。

Job 允許我們定制任務的執行時間,并提供了靈活的處理方式,還可以通過配置,安排任務在系統用戶訪問量少的時段內執行,極大地提高了工作效率。例如,對于數據庫日常的備份、更新、刪除和復制等耗時長、重復性強的工作,以及電信增值短信業務中的定時 PUSH,我們就可以利用 Job 去自動執行以減少工作量。
   
目前,流行的主流數據庫都擁有此項功能,最具代表性的是 Microsoft SQL Server 7.0、Oracle8i/9i 等。但是,要讓 Job 工作,還需要我們加以配置才能實現。這些配置都有 GUI 操作。本文介紹 Oracle9i 以后通過命令行實現 Job 配置。
前提:寫好的要定時執行的存儲過程 [不能帶參數]。
定義一個 Job,執行間隔是需要注意的一件重要的事情。SYSDATE+1/24 是存儲在 dba_jobs 視圖中的間隔,它可以產生每小時一次的快照。可以將這個數據改變為不同的采樣時間,在一天中有 24*60 = 1440 分鐘,可以使用這個數字調整執行次數。比方說:我希望在每 10 分鐘獲取一次快照,應該使用下列命令:

execute dbms_job.submit(
  :jobno,                        – 作業編號
  ,  – 執行的過程
  trunc(sysdate+10/1440, MI),  – 下次執行時間
  trunc(sysdate+10/1440, MI) ,  – 間隔時間
  true,  –no_parse
  :instno);

1. 創建 JOB
創建一個任務,執行間隔是每 5 分鐘。
  Variable v_sn number;

  Begin
  dbms_job.submit(:v_sn,
  p_push_send; ,
  trunc(sysdate+5/1440, MI),
  trunc(sysdate+5/1440, MI)
  commit;
  end;
  /

刪除一個任務:
execute dbms_job.remove(jobno);

2. 查詢任務語句
涉及兩個表:dba_jobs 及 dba_jobs_running
select * from dba_jobs;
select * from dba_jobs_running;

select
job,what,to_char(last_date, yyyy-mm-dd
HH24:mi:ss ),to_char(next_date, yyyy-mm-dd HH24:m),interval from
dba_jobs where job in (325,295)

select job,what,last_date,next_date,interval from  dba_jobs where job in (1,3);

3. 必要的參數[修改 initsid.ora 參數]
job_queue_processes = 4  – 可執行作業個數
job_queue_interval = 10  – 默認間隔延遲時間 10s
job_queue_keep_connections=true  –job 保持正常連接

修改可執行作業個數為 20 個:
ALTER SYSTEM SET JOB_QUEUE_PROCESSES = 2;0

修改取消限制模式:
ALTER SYSTEM DISABLE RESTRICTED SESSION;

4. 相關的幾個 Job 操作
刪除 job:
exec dbms_job.remove(jobno);

修改要執行的操作:
exec dbms_job.what(jobno,what);

修改下次執行時間:
exec dbms_job.next_date(job,next_date);

修改間隔時間:
exec dbms_job.interval(job,interval);

停止 job:
exec dbms.broken(job,broken,nextdate);

啟動 job:
exec dbms_job.run(jobno);

5. 關于 Job 的延遲
Job 都有不同程度的延遲,想完全排除這種誤差最好使用操作系統的定時器 crontab 或者 at,哈哈,開個玩笑。
A 時間重疊的問題[網友論]:
比如我有兩個 JOB,都是在凌晨 3 點運行,那么如果其中一個在 3 點運行,那么另一個必須等待第一個 JOB 完成,然后才能執行。特別是有些象 sysdate+1/24,這樣每隔一小時運行的 JOB 就更容易沖突;即使沒有時間重疊,ORACLE 也是按 job_queue_internal(通常是 1 分鐘)的間隔進行檢查 JOB 隊列,這樣 1 點鐘的作業正好在 3:00:45 才檢查到,那么就會在 3:00:45 才執行該 job. 我們知道 ORACLE JOB 如果第一次執行失敗,那么按一定的時間間隔再次啟動該 JOB 直到成功,如果直到運行 16 次還是失敗,那么就中斷該 JOB,所以實際運行的時間會進行推遲。

B 采用 精確定時 函數(從前面可能看到,其實是很難實現精確定時執行 JOB 的)
我們可以采用如 trunc(sysdate)+(1+24)/25 或 trunc(sysdate)+25/24。表示每天 1 點執行 job,這樣就不會受上次 JOB 延時的影響。(沒測過)。
 
 
6. 一個簡單例子:

6.1 創建測試表
SQL create table T(a date);
表已創建。

6.2 創建一個自定義過程
SQL create or replace procedure MYPROC as
  begin
  insert into T values(sysdate);
  end;
  /
過程已創建。

6.3 創建 JOB
SQL variable job1 number;
SQL begin
    dbms_job.submit(:job1, MYPROC; ,sysdate, sysdate+1/1440 – 每天 1440 分鐘,即一分鐘運行 test 過程一次
    end;
    /

PL/SQL 過程已成功完成。

SQL print  job1;

  JOB1
———-
  3

6.4 運行 JOB
SQL begin
  dbms_job.run(:job1);
  end;
  /

PL/SQL 過程已成功完成。
SQL

—- 驗證
SQL select to_char(a, yyyy/mm/dd hh34:mi:ss) 時間 from T;

時間
——————-
2017/11/09 14:54:14

SQL alter session set nls_date_format= yyyy-mm-dd hh34:mi:ss

Session altered.

SQL select sysdate from dual;

SYSDATE
——————-
2017-11-09 14:56:05

SQL select to_char(a, yyyy/mm/dd hh34:mi:ss) 時間 from T;

時間
——————-
2017/11/09 14:54:14
2017/11/09 14:55:14

SQL select to_char(a, yyyy/mm/dd hh34:mi:ss) 時間 from T;

時間
——————-
2017/11/09 14:54:14
2017/11/09 14:55:14
2017/11/09 14:56:14

SQL

6.5 刪除 JOB
SQL begin
  dbms_job.remove(:job1);
  end;
  /

PL/SQL 過程已成功完成。

6.6 創建 DBMS_JOB.submit 注意點:
為什么剛剛創建后的 JOB 不能自動的執行呢?這是一個疏忽導致的!
在創建 JOB 的時候,需要在結尾處指定“COMMIT;”!表示創建完成之后便執行一次。

– 刪除之前的 JOB,重新創建一個帶有“COMMIT”語句的新 JOB。
SQL variable job1 number;
SQL begin
    dbms_job.submit(:job1, MYPROC; ,sysdate, sysdate+1/1440
    commit;
    end;
    /

PL/SQL procedure successfully completed.

SQL

SQL print job1;

  JOB1
———-
  4

此次創建的 JOB 信息如下,可見 LAST_DATE 在創建完之后便有內容,表示已經被執行了一次。
SQL col log_user for a10
SQL col INTERVAL for a30
SQL col what for a30
SQL select job,log_user,to_char(last_date, yyyy-mm-dd hh34:mi:ss) last_date,to_char(next_date, yyyy-mm-dd hh34:mi:ss) next_date,interval, what from user_jobs;

  JOB LOG_USER  LAST_DATE  NEXT_DATE  INTERVAL  WHAT
———- ———- ——————- ——————- —————————— ——————————
  4 SYS  2017-11-09 15:02:34 2017-11-09 15:03:34 sysdate+1/1440  MYPROC;

SQL
SQL select to_char(a, yyyy/mm/dd hh34:mi:ss) 時間 from T;

時間
——————-
2017/11/09 14:54:14
2017/11/09 14:55:14
2017/11/09 14:56:14
2017/11/09 14:57:14
2017/11/09 14:58:14
2017/11/09 14:59:14
2017/11/09 15:00:32
2017/11/09 15:00:34
2017/11/09 15:01:34
2017/11/09 15:02:34

10 rows selected.

6.7 再次運行之前的未加 commit 的 dbms_job.SUBMIT 包
先刪除:
SQL begin
  dbms_job.remove(:job1);
    end;
    /

PL/SQL procedure successfully completed.

SQL select to_char(a, yyyy/mm/dd hh34:mi:ss) 時間 from T;

時間
——————-
2017/11/09 14:54:14
2017/11/09 14:55:14
2017/11/09 14:56:14
2017/11/09 14:57:14
2017/11/09 14:58:14
2017/11/09 14:59:14
2017/11/09 15:00:32
2017/11/09 15:00:34
2017/11/09 15:01:34
2017/11/09 15:02:34
2017/11/09 15:03:34

時間
——————-
2017/11/09 15:04:34
2017/11/09 15:05:34
2017/11/09 15:06:34
2017/11/09 15:07:34

15 rows selected.

SQL select job,log_user,to_char(last_date, yyyy-mm-dd hh34:mi:ss) last_date,to_char(next_date, yyyy-mm-dd hh34:mi:ss) next_date,interval, what from user_jobs;

no rows selected

– 運行 dbms_job.submit:
SQL variable job1 number;
SQL begin
  dbms_job.submit(:job1, MYPROC; ,sysdate, sysdate+1/1440
    end;
  /

PL/SQL procedure successfully completed.

SQL print job1;

  JOB1
———-
  5

– 查詢 user_jobs:
SQL select job,log_user,to_char(last_date, yyyy-mm-dd hh34:mi:ss) last_date,to_char(next_date, yyyy-mm-dd hh34:mi:ss) next_date,interval, what from user_jobs;

  JOB LOG_USER  LAST_DATE  NEXT_DATE  INTERVAL  WHAT
———- ———- ——————- ——————- —————————— ——————————
  5 SYS  2017-11-09 15:08:34 sysdate+1/1440  MYPROC;

SQL
SQL select to_char(a, yyyy/mm/dd hh34:mi:ss) 時間 from T;

時間
——————-
2017/11/09 14:54:14
2017/11/09 14:55:14
2017/11/09 14:56:14
2017/11/09 14:57:14
2017/11/09 14:58:14
2017/11/09 14:59:14
2017/11/09 15:00:32
2017/11/09 15:00:34
2017/11/09 15:01:34
2017/11/09 15:02:34
2017/11/09 15:03:34

時間
——————-
2017/11/09 15:04:34
2017/11/09 15:05:34
2017/11/09 15:06:34
2017/11/09 15:07:34

15 rows selected.

SQL  

注意:此處的 LAST_DATE 內容是空,表示此 JOB 沒有被執行過,因此這個 JOB 將永遠不會被自動的執行。

那么,如何才能使它自動執行起來呢?很簡單,只要我們手動將這個 JOB 執行一下即可。

到此,關于“Oracle job 定時任務怎么理解”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-15發表,共計10436字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 常德市| 卢氏县| 福建省| 太湖县| 三亚市| 本溪| 腾冲县| 佛坪县| 广汉市| 商水县| 大丰市| 大同市| 璧山县| 汉沽区| 吉隆县| 临江市| 宁乡县| 萨迦县| 靖安县| 十堰市| 竹北市| 翼城县| 全州县| 仁布县| 四川省| 县级市| 亚东县| 镇康县| 崇州市| 新安县| 马关县| 利川市| 浙江省| 莲花县| 定兴县| 堆龙德庆县| 赤壁市| 榕江县| 双流县| 襄垣县| 伊通|