Job队列的管理
之前学习过一次Job的管理了,但是这次在学习DBA的时候看到,就从理论的高度再重新全面得学习一回。Job的管理比较简单,主要就是对DBMS_JOB这个包的应用和一些参数的设置,而且DBMS_JOB包也比较简单,不需要太复杂的记忆,基本上看一遍就能记住。在建立JOB的时候,最需要注意的还是时间的偏移问题,需要解决好。
一、Job执行基础知识
1、作业队列进程(Jnnn)
Oracle使用Job队列进程(Jnnn)来执行作业队列中的Job。对于每一个实例,这些Job队列进程都是由Job队列协调程序(CJQ0)后台进程动态派生的。
CJQ0定期从DBA_JOBS视图中选出准备运行的Job,并按时间排序,然后派生出Jnnn进程运行选中的Job,每个Jnnn执行一个Job。
2、JOB_QUEUE_PROCESSES参数
JOB_QUEUE_PROCESSES参数用于控制一个实例上能够并发运行Jnnn进程的最大数目,例如:
JOB_QUEUE_PROCESSES = 60 指同一时间最多并发处理60个Job
另:如果JOB_QUEUE_PROCESSES = 0则表示数据库启动时不启动任何Job队列协调程序进程,也不执行任何Job
3、JOB_QUEUE_PROCESSES的修改
Jnnn由Job队列协调进程创建,每次按需要创建Job队列所需的最多的Jnnn进程。当Jnnn执行完某个Job时,它将轮询另一个要执行的Job,如果没有要执行的Job,则该进程进入空闲状态,并在指定时间后再次轮询,在轮询到预定次数后,如果还没有找到要执行的作业,则该进程终止。
ALTER SYSTEM SET JOB_QUEUE_PROCESSES; 可用该语句动态修改最大并发Jnnn进程数目
注1:如果ALTER SYSTEM修改后的JOB_QUEUE_PROCESSES小于当前执行的Jnnn数,则允许超出的执行完当前任务。
注2:如果实例运行在受限模式,则Jnnn进程不执行Job
二、管理Job队列
1、DBMS_JOB包
Oracle中使用DBMS_JOB包来执行JOB的管理操作,具体包括以下过程:
SUBMIT :将Job提交到Job队列
REMOVE :从Job队列中删除指定Job
CHANGE :修改Job( WHAT + NEXT_DATE + INTERVAL )
WHAT :修改Job的说明(SQL语句)
NEXT_DATE :修改Job的下一次执行时间
INTERVAL :修改Job的执行间隔
BROKEN :设置Job损坏标记(不再执行)
RUN :强制执行Job
2、DBMS_JOB.SUBMIT
使用DBMS_JOB.SUBMIT来提交JOB,主要有以下参数:
JOB :这是一个输出参数,是系统分配给JOB的标识符。
WHAT :希望执行的PL/SQL代码
NEXT_DATE :Job下一次运行的日期,默认为SYSDATE
INTERVAL :计算下一次执行的日期,默认值为NULL
NO_PARSE :TRUE-分析与首次执行Job相关联的过程;FALSE-分析与Job相关的过程(???)
具体的说明如下:
a) 作业环境
当Job被提交时,Oracle还会记录以下信息:
* 当前user
* 提交或更改Job的user
* 当前schema(可能用了alter session set current_schema语句)
* MAC权限
* NLS_LANGUAGE
* NLS_TERRITORY
* NLS_CURRENCY
* NLS_ISO_CURRENCY
* NLS_NUMERIC_CHARACTERS
* NLS_DATE_FORMAT
* NLS_DATE_LANGUAGE
* NLS_SORT
b) Job的导入和导出
可以在数据库之间导入和导出Job,如果导入时的标识符相同,则不能导入,作为新Job提交
c) Job所有者
提交者即为Job的所有者,只有Job的所有者可以对Job进行修改、强制执行、删除
d) Job号码
用于区分的唯一标识符,由SYS.JOBSEQ序列自动产生,永远不能修改,除非删除重建
e) Job定义
一般在SUBMIT中的WHAT参数都是对某个过程的调用,使用单引号标注。
注:不能从一个Job中run另一个Job(remove等其他操作是可以的)
f) Job执行间隔
在Job当前执行完成后,会马上计算INTERVAL的指,来指定下一次的运行时间,下面的INTERVAL指都是正确的:
'SYSDATE + 7' --本次执行后的7天
'SYSDATE + 1/48' --本次执行后的半小时
'NEXT_DAY(TRUNC(SYSDATE),''MONDAY'') + 15/24' --每个星期一下午3点
'NEXT_DAY(ADD_MONTHS(TRUNC(SYSDATE,''Q''),3),''THURSDAY'')' --每个季度星期四
注:要注意其中的''分隔
g) 数据库链接和Job
如果在Job中使用到了数据库的链接,那么必须包括用户名和密码,如果是匿名链接,则提交不成功
3、Job的执行
Jnnn执行Job时,拥有Job所有者的默认权限,所有者必须为Job中引用的所有对象授予所需的对象权限
当用DBMS_JOB.RUN强制执行Job时:用户只有所有者的默认权限,所有用过角色授予Job所有者的权限都不可用
a) Job队列锁
Oracle使用Job队列锁确保每次Job只在一个会话中执行。
通过查找V$JOB视图的'JQ'类型锁,可以查看明细信息:
SELECT SID,TYPE,ID1,ID2 FROM V$LOCK WHERE TYPE = 'JQ'; --ID2表示Job标识符
b) Job执行错误
Job执行失败时,报ORA-12012错,主要是这样几个原因:
① 网络失败或实例失败
② 当执行Job时发生异常情况
若Job返回错误,则Oracle会在1分钟后重试,然后在2分钟后重试,再在4分钟后重试,每次间隔都是前一次的2倍。
直到失败16次,则将该Job标记为“损坏”,并且不再尝试执行该Job。
4、删除Job
DBMS_JOB.REMOVE(14144); --直接输入Job号即可
限制:
① 可以删除目前正在执行的Job,但Job会执行完成当前任务后再被删除
② 只能删除自己的所有Job,若要删除其他user的Job,会报错Job不在列表中
5、更改Job
使用CHANGE、WHAT、NEXT_DATE、INTERVAL来修改,只要注明Job号即可。
限制:还是只能修改自己所有的Job
6、损坏的Job
Job被标记为损坏只有两种途径:
① 尝试执行16次失败
② 用DBMS_JOB.BROKEN标记为损坏
运行被标注为损坏的Job也只有两种途径:
① 用DBMS_JOB.RUN强制执行
② 用DBMS_JOB.BROKEN标记用未损坏
示例:
DBMS_JOB.BROKEN(14144, TRUE); --标记为损坏
DBMS_JOB.BROKEN(14144, FALSE, NEXT_DAY(SYSDATE, 'MONDAY')); --标记为未损坏并设置执行间隔
7、强制执行Job
直接用 DBMS_JOB.RUN(14144); 来强制执行Job
注意:一但使用RUN后将不能回滚该Job,而且INTERVAL将会重新计算下一次执行时间
8、终止Job
使用 DBMS_JOB.BROKEN 或 KILL SESSION 两种方法来终止Job
三、查看Job信息
DBA_JOBS:所有Job的信息
ALL_JOBS:当前用户可以访问的所有Job信息
DBA_JOBS_RUNNING:当前运行的Job信息