Oracle作业(JOB)更新next_date的探讨

** Oracle ** ** 作业 ** ** (JOB) ** ** 更新 ** ** next_date ** ** 的探讨 ** ** **


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


** 摘要 ** : 本文通过实验和事件跟踪来分析 Oracle Job 执行过程中修改下次执行时间的机制。

有些人问, Oracle 的 JOB 在设定完 next_date 和 interval 之后,到底是什么时候决定下一次运行时间的。可以归纳成以下几个问题。

1 . 假设我们的 JOB 设定第一次运行的时间是 12:00 ,运行的间隔是 1 小时, JOB 运行需要耗时 30 分钟,那么第二次运行是在 13:00 还是 13:30 ?

2 . 如果是在 13:00 那是不是说明只要 JOB 一开始运行, next_date 就被重新计算了?

3 . JOB 的下一次运行会受到上一次运行时间的影响吗?如果受到影响,如何可以避免这个影响而让 JOB 在每天的指定时刻运行?

本文通过一些实验和跟踪来解释上面的所有问题。

首先我们选择一个测试用户,假设该用户名为 kamus 。

由于我们在实验用的存储过程中会用到 dbms_lock 包,所以需要由 sys 用户先授予 kamus 用户使用 dbms_lock 包的权限。

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;

授权成功。

然后用 kamus 用户登录数据库,创建我们测试使用的存储过程 sp_test_next_date 。

create or replace procedure sp_test_next_date as
p_jobno number;
P_nextdate date;
begin
_ -- _ _ 将调用此存储过程的 _ _ job _ _ 的 _ _ next_date _ _ 设置为 _ _ 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 执行中的 next_date: ' ||
to_char(p_nextdate, 'YYYY-MM-DD HH24:MI:SS' ));
_ -- _ _ 等待 _ _ 10 _ _ 秒再退出执行 _
dbms_lock.sleep(seconds => 10 );
end sp_test_next_date;

创建调用该存储过程的 JOB ,定义 interval 为每天一次,也就是这次执行以后,下次执行时间应该在 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

然后我们手工执行存储过程,执行完毕以后再手工从 user_jobs 视图中获得 JOB 的下次执行时间,可以看到在存储过程中修改的 JOB 的下次执行时间已经生效,变成了当前时间的 30 分钟以后,而不是默认的 1 天以后。

SQL> conn kamus

请输入口令 :

已连接。

SQL> set serverout on

SQL> exec sp_test_next_date();

JOB 执行中的 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 ,看看这次的结果,可以发现 JOB 没有运行完毕以前被修改了的下次运行时间跟 JOB 运行完毕以后再次手工检索 user_jobs 视图获得的下次运行时间已经不相同了。由此我们可以得出一个结论, next_date 是在 JOB 运行完毕以后被 Oracle 自动修改的,而不是在 JOB 刚开始运行的时候,因为我们在存储过程中修改的 next_date 在 JOB 运行结束之后又被修改为默认的 1 天以后了。

SQL> exec dbms_job.run(1);

JOB 执行中的 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

现在我们再次修改存储过程,输出存储过程开始执行的时间,便于跟执行完毕以后的 JOB 下次执行时间进行比较。

create or replace procedure sp_test_next_date as
p_jobno number;
P_nextdate date;
begin
_ -- _ _ 输出 _ _ JOB _ _ 刚开始执行的时间 _
dbms_output.put_line( ' JOB 开始执行的时间 : ' ||
to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS' ));
_ -- _ _ 将调用此存储过程的 _ _ job _ _ 的 _ _ next_date _ _ 设置为 _ _ 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 _
<SPAN lan

Published At
Categories with 数据库类
comments powered by Disqus