如何定时Oracle中的Job

目前,流行的主流数据库都拥有此项功能,最具代表性的是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, --作业编号
‘sp;', --执行的过程
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.查询任务语句

涉及两个表:user_jobs及dba_jobs_running[视图dba_jobs]
select * from user_jobs;
select * from dba_jobs_running;
select * from dba_jobs;

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:dbms_job.remove(jobno);
修改要执行的操作:dbms_job.what(jobno,what);
修改下次执行时间:dbms_job.next_date(job,next_date);
修改间隔时间:dbms_job.interval(job,interval);
停止job:dbms.broken(job,broken,nextdate);
启动job: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延时的影响。(没测过)。
C我自己执行的那个每格5分钟的Job,我看了好象没有延迟,可能是执行时间短,间隔也小,就没有察觉。


如果给你带来帮助,欢迎微信或支付宝扫一扫,赞一下。