http://www.cnblogs.com/snowballed/p/7245739.html
在前面学习了存储过程的开发、调试之后,我们现在就需要来使用存储过程了。简单的使用,像上篇《懵懂oracle之存储过程2》中提到的存储过程调用,我们可以将写好的存储过程在另一个PL/SQL块亦或是另一个存储过程中调用执行,而很多情况下,我们往往需要定时执行这个存储过程,那么我们就需要使用到Oracle的JOB,让我们的数据库可以定期的执行特定的任务。
下面就让我们来了解下JOB的方方面面:
在Oracle 10g以前,Oracle提供了dbms_job系统包来实现job,到Oracle 10g时,就多出了dbms_scheduler包来实现job,它比dbms_job拥有更强大的功能和更灵活的机制,在本文暂只介绍dbms_job的知识,所用的数据库版本Oracle 11g。
1 初始化
1.1 初始化权限
使用dbms_job包如果遇到权限问题,那么需要使用管理员账号给此用户赋予权限:
1 grant execute on dbms_job to 用户;
1.2 初始化参数
重点关注job_queue_processes参数,它告诉了数据库最多可创建多少个job进程来运行job,可通过下面语句查询改参数值情况:
select name,value,display_value from v$parameter where name in ('spfile',job_queue_processes');
当job_queue_processes参数对应的value为0时,则代表所有创建的job都不会运行,因此我们需将此参数值根据各自需要修改至n(1~1000):
- 当上述语句未查询出spfile参数时,则表示数据库以pfile启动,该文件默认位置为%ORACLE_HOME%database目录下的init<sid>.ora文件(sid-->数据库实例名)。此时若要修改参数值,则需打开此文件进行增加或修改下行信息,而后重启数据库才能生效:
1 JOB_QUEUE_PROCESSES=n
-
当上述语句可查询出spfile参数时,则表示数据库以spfile启动,该文件的位置可从value值中得到。此时若要修改参数值,则可通过在数据库执行下列语句进行修改:
alter system set job_queue_processes=n;
2 /*
3 alter system 参数名=值 [scope=应用范围];
4 scope需知:
5 scope=both,表示修改会立即生效且会修改spfile文件以确保数据库在重启后也会生效如果(以spfile启动此项为缺省值);
6 scope=memory,表示修改会立即生效但不会修改spfile文件,因此重启后失效(以pfile启动此项为缺省值,且只可设置这个值);
7 scope=spfile,表示只修改spfile文件,在重启数据库后才生效(对应静态参数则只可设置此项值,设置其它值会报错:
8 ORA-02095: specified initialization parameter cannot be modified)。
9 */
2 dbms_job包分析(可在数据库中查看此包获取相关信息,暂未分析包内user_export存过的用法)
2.1 内部存过参数汇总
2.2 内部存过详解
1 create or replace procedure sp_test_hll_170726 AUTHID CURRENT_USER as
2 v_flag number;
3 begin
4 select count(1)
5 into v_flag
6 from user_tables
7 where table_name = TEST_TABLE_170726';
8 if v_flag = 0 then
9 execute immediate create table test_table_170726(id number,create_time date default sysdate)10 end if;
11 12 13 from user_sequences
14 where sequence_name SEQ_TEST_TABLE_170726_ID15 16 create sequence seq_test_table_170726_id17 18 insert into test_table_170726(id) values(seq_test_table_170726_id.nextval)19 commit;
20 end sp_test_hll_170726;
21 /
1)submit:用于新建一个定时任务
2)isubmit:用于新建一个定时任务同时指定JOB编号
- 定义:
procedure isubmit(job in binary_integer,128); line-height:1.5!important">2 what 3 next_date in date,128); line-height:1.5!important">4 interval 5 no_parse default false);
- 范例:
2 dbms_job.isubmit(23,128); line-height:1.5!important">指定job编号,不可用已有job的编号,否则报违反唯一约束的异常
3 4 5 17 sysdate,128); line-height:1.5!important">18 trunc(sysdate + numtoyminterval(1,0); line-height:1.5!important">yyyy)+1/24每年一月一号一点执行
19 );
20 21 22
- 备注:
除job为入参需指定外,其它使用情况与submit相同,指定job编号时,不可用已存在job的编号,否则导致异常ORA00001: 违反唯一约束条件 (SYS.I_JOB_JOB)。
3)remove:用于从JOB任务队列中移除一个JOB(不会中断仍在运行的JOB)
- 定义:
procedure remove(job in binary_integer);
- 范例:
2 dbms_job.remove(23);
3 5 /
- 备注:
移除需移除已存在JOB,否则导致异常23421: 作业编号111在作业队列中不是一个作业。
4)what:用于修改what参数值
- 定义:
procedure what(job in binary_integer,what varchar2);
- 范例:
2 jobno 4 select job into jobno from user_jobs where what like %sp_test_hll_170726%5 dbms_job.what(jobno,0); line-height:1.5!important">begin sp_test_hll_170726; end;'); 修改成pl/sql块形式
6 8
5)next_date:用于修改next_date参数值
- 定义:
procedure next_date(job in date);
- 范例:
5 dbms_job.next_date(jobno,trunc(sysdate 1)); 修改最近一次待执行的时间至明天凌晨
6)interval:用于修改interval参数值
- 定义:
procedure interval(job 5 dbms_job.interval(jobno,0); line-height:1.5!important">sysdate + 1修改为每隔一天运行一次
7)instance:用于修改instance、force参数值
- 定义:
procedure instance(job 2 instance 3 force 5 dbms_job.instance(jobno,0); line-height:1.5!important">1); 修改为数据库实例1才能运行此定时任务
- 备注:
请勿修改已在运行的JOB的数据库实例,根据网络搜索得知:job会不再运行,并出现等待事件:enq: TX - row lock contention,执行的sql是update sys.job$setthis_date=:1wherejob=:2,也就是在更新sys的sys.job$表,最后只能杀掉此会话,才消除此等待事件。 一般情况下,建立不要指定JOB在特定实例运行,通常都默认为0。 下面change也需注意此处备注。
8)change:用于修改what、next_date、interval、instance、force参数值
- 定义:
procedure change(job 5 instance default null,128); line-height:1.5!important">6 force 5 dbms_job.change(jobno,128); line-height:1.5!important"> 6 7 sysdate,128); line-height:1.5!important"> 8 sysdate + 1/24');实现多参数修改
9 11
9)broken:用于给定时任务添加或去除中断标识,将任务挂起或取消挂起(不会中断仍在运行的JOB)
- 定义:
procedure broken(job 2 broken in boolean,255); line-height:1.5!important">default sysdate);
- 范例:
5 dbms_job.broken(jobno,true);挂起
- 备注:
挂起时,会修改JOB任务队列中字段broken='Y',next_date='4000/1/1',next_sec='00:00:00',只要broken='Y',就算next_date<sysdate,此任务也不会执行; 取消挂起时,会修改broken='N',next_date与next_sec安照next_date参数值进行调整,任务查询开始按计划执行。
10)run:用于立即执行此定时任务(被broken挂起的存过也会取消挂起并运行)
- 定义:
procedure run(job 5 dbms_job.run(jobno);立即运行
- 备注:
当任务挂起时,会修改broken='N'; 当数据库实例不符时也可通过修改force=true以强制在当前数据库实例运行,确保run能一定运行此项任务。
3 JOB任务队列查询处理汇总
3.1 表汇总(SYS.JOB$、DBA_JOBS、ALL_JOBS、USER_JOBS、DBA_JOBS_RUNNING)
在通过上面介绍的dbms_job包对JOB进行的处理,实际上处理的是数据库的任务队列表SYS.JOB$,我们可以通过下面语句查看该表情况:
select t.job,t.lowner,t.powner,t.cowner,t.last_date,t.this_date,t.next_date,t.total,t.interval#,t.failures,t.flag,t.what,128); line-height:1.5!important">2 t.nlsenv,t.env,t.charenv,t.field1,t.scheduler_flags,t.xid
3 /*,t.cur_ses_label,t.clearance_hi,t.clearance_lo
不能查询这三个字段,会报异常ORA-00932: 数据类型不一致: 应为 NUMBER,但却获得 LABEL
它们的数据类型为MLSLABEL,在TRUSTED ORACLE中用来保存可变长度二进制标签。
6 from sys.job$ t;
但是它的数据长得不好看,Oracle提供了我们两个视图(DBA_JOBS、USER_JOBS)可以查看:
view sys.dba_jobs select JOB,lowner LOG_USER,powner PRIV_USER,cowner SCHEMA_USER,128); line-height:1.5!important"> 3 LAST_DATE,substr(to_char(last_date,0); line-height:1.5!important">HH24:MI:SS'),0); line-height:1.5!important">8) LAST_SEC,128); line-height:1.5!important"> 4 THIS_DATE,substr(to_char(this_date,0); line-height:1.5!important">8) THIS_SEC,128); line-height:1.5!important"> 5 NEXT_DATE,substr(to_char(next_date,0); line-height:1.5!important">8) NEXT_SEC,128); line-height:1.5!important"> 6 (total+(sysdate-nvl(this_date,sysdate)))*86400 TOTAL_TIME,128); line-height:1.5!important"> 7 decode(mod(FLAG,0); line-height:1.5!important">2),0); line-height:1.5!important">Y0,0); line-height:1.5!important">N?') BROKEN,128); line-height:1.5!important"> 8 INTERVAL# interval,FAILURES,WHAT,128); line-height:1.5!important"> 9 nlsenv NLS_ENV,env MISC_ENV,j.field1 INSTANCE
from sys.job$ j
where BITAND(j.scheduler_flags,0); line-height:1.5!important">2) IS NULL OR
12 BITAND(j.scheduler_flags,0); line-height:1.5!important">2) don't show jobs with drop flag */;
13 comment on table SYS.DBA_JOBS is All jobs in the database14 comment column SYS.DBA_JOBS.JOB Identifier of job. Neither import/export nor repeated executions change it.15 comment column SYS.DBA_JOBS.LOG_USER USER who was logged in when the job was submitted16 comment column SYS.DBA_JOBS.PRIV_USER USER whose default privileges apply to this job17 comment column SYS.DBA_JOBS.SCHEMA_USER select * from bar means select * from schema_user.bar 18 comment column SYS.DBA_JOBS.LAST_DATE Date that this job last successfully executed19 comment column SYS.DBA_JOBS.LAST_SEC Same as LAST_DATE. This is when the last successful execution started.20 comment column SYS.DBA_JOBS.THIS_DATE Date that this job started executing (usually null if not executing)21 comment column SYS.DBA_JOBS.THIS_SEC Same as THIS_DATE. This is when the last successful execution started.22 comment column SYS.DBA_JOBS.NEXT_DATE Date that this job will next be executed23 comment column SYS.DBA_JOBS.NEXT_SEC Same as NEXT_DATE. The job becomes due for execution at this time.24 comment column SYS.DBA_JOBS.TOTAL_TIME Total wallclock time spent by the system on this job,in seconds25 comment column SYS.DBA_JOBS.BROKEN If Y,no attempt is being made to run this job. See dbms_jobq.broken(job).26 comment column SYS.DBA_JOBS.INTERVAL A date function,evaluated at the start of execution,becomes next NEXT_DATE27 comment column SYS.DBA_JOBS.FAILURES How many times has this job started and failed since its last success?28 comment column SYS.DBA_JOBS.WHAT Body of the anonymous PL/SQL block that this job executes29 comment column SYS.DBA_JOBS.NLS_ENV alter session parameters describing the NLS environment of the job30 comment column SYS.DBA_JOBS.MISC_ENV a versioned raw maintained by the kernel,for other session parameters31 comment column SYS.DBA_JOBS.INSTANCE Instance number restricted to run the job';
view sys.user_jobs select j."JOB",j."LOG_USER",j."PRIV_USER",j."SCHEMA_USER",j."LAST_DATE",j."LAST_SEC",j."THIS_DATE",j."THIS_SEC",j."NEXT_DATE",j."NEXT_SEC",j."TOTAL_TIME",j."BROKEN",j."INTERVAL",j."FAILURES",j."WHAT",j."NLS_ENV",j."MISC_ENV",j."INSTANCE" from dba_jobs j,sys.user$ u where
3 j.priv_user = u.name
4 and u.user# = USERENV(SCHEMAID');
5 comment table SYS.USER_JOBS All jobs owned by this user 6 comment column SYS.USER_JOBS.JOB 7 comment column SYS.USER_JOBS.LOG_USER 8 comment column SYS.USER_JOBS.PRIV_USER 9 comment column SYS.USER_JOBS.SCHEMA_USER 10 comment column SYS.USER_JOBS.LAST_DATE 11 comment column SYS.USER_JOBS.LAST_SEC 12 comment column SYS.USER_JOBS.THIS_DATE column SYS.USER_JOBS.THIS_SEC column SYS.USER_JOBS.NEXT_DATE column SYS.USER_JOBS.NEXT_SEC column SYS.USER_JOBS.TOTAL_TIME column SYS.USER_JOBS.BROKEN column SYS.USER_JOBS.INTERVAL column SYS.USER_JOBS.FAILURES column SYS.USER_JOBS.WHAT column SYS.USER_JOBS.NLS_ENV column SYS.USER_JOBS.MISC_ENV column SYS.USER_JOBS.INSTANCE
同时通过下面语句我们可以知道,还有一个同义词ALL_JOBS:
select *
2 from all_objects t
3 where t.object_name DBA_JOBSALL_JOBSUSER_JOBS5 from sys.all_synonyms
6 where synonym_name ');
我们通过下面语句都能查询我们建立好的JOB的信息:
* from dba_jobs;
from all_jobs;
from user_jobs;
DBA_JOBS/ALL_JOBS/USER_JOBS各字段的含义如下:
1 字段(列) 数据类型 描述
2 JOB NUMBER 任务的唯一标示号
3 【Identifier of job. Neither import/export nor repeated executions change it.】
4 LOG_USER VARCHAR2(30) 提交任务时登录的用户
5 【USER who was logged when the job was submitted】
6 PRIV_USER 30) 任务默认权限对应的用户
7 【USER whose privileges apply to this job】
8 SCHEMA_USER 30) 对任务作语法分析的用户模式(查询bar表代表查询schema_user.bar表)
9 【from bar means from schema_user.bar】
10 LAST_DATE DATE 最后一次成功运行任务的时间
11 【Date that this job last successfully executed】
12 LAST_SEC 32) 长度为8的HH24:MI:SS格式的LAST_DATE
13 【Same as LAST_DATE. This is when the last successful execution started.】
14 THIS_DATE DATE 正在运行任务的开始时间,如果没有运行任务则为null
15 【Date that this job started executing (usually if not executing)】
16 THIS_SEC 32) 长度为8的HH24:MI:SS格式的THIS_DATE
17 【Same as THIS_DATE. This 18 NEXT_DATE DATE 下一次定时运行任务的时间
19 【Date that this job will next be executed】
20 NEXT_SEC 32) 长度为8的HH24:MI:SS格式的NEXT_DATE
21 【Same as NEXT_DATE. The job becomes due for execution at this time.】
22 TOTAL_TIME NUMBER 数据库用于执行此任务的总秒数统计
23 【Total wallclock time spent by the system on this job,128); line-height:1.5!important">in seconds】
24 BROKEN 1) 中断标识,Y表示任务中断,不再尝试执行此任务
25 【If Y,no attempt is being made to run this job. See dbms_jobq.broken(job).】
26 INTERVAL 200) 用于计算下此运行时间的时间表达式
27 【A date function,evaluated at the start of execution,becomes next NEXT_DATE】
28 FAILURES NUMBER 自最后一次成功之后任务运行失败的总次数
29 【How many times has this job started and failed since its last success?】
30 WHAT 4000) 任务执行的匿名PL/SQL块
31 【Body of the anonymous PL/SQL block that this job executes】
32 NLS_ENV 4000) 任务运行的NLS会话设置
33 【alter session parameters describing the NLS environment of the job】
34 MISC_ENV RAW(32) 任务运行的其他一些会话参数
35 【a versioned raw maintained by the kernel,255); line-height:1.5!important">for other session parameters】
36 INSTANCE NUMBER 任务执行时限制关联的数据库实例
37 【Instance number restricted to run the job】
同时,Oracle还提供了DBA_JOBS_RUNNING视图供我们查询正在运行的任务:
view sys.dba_jobs_running select v.SID,v.id2 JOB,j.FAILURES,128); line-height:1.5!important"> 5 j.field1 INSTANCE
6 from sys.job$ j,v$lock v
7 where v.type JQ' and j.job (+)= v.id2;
table SYS.DBA_JOBS_RUNNING All jobs in the database which are currently running,join v$lock and job$column SYS.DBA_JOBS_RUNNING.SID Identifier of process which is executing the job. See v$lock.column SYS.DBA_JOBS_RUNNING.JOB Identifier of job. This job is currently executing.column SYS.DBA_JOBS_RUNNING.FAILURES column SYS.DBA_JOBS_RUNNING.LAST_DATE column SYS.DBA_JOBS_RUNNING.LAST_SEC column SYS.DBA_JOBS_RUNNING.THIS_DATE column SYS.DBA_JOBS_RUNNING.THIS_SEC column SYS.DBA_JOBS_RUNNING.INSTANCE The instance number restricted to run the job
通过下面语句可简单查询该表情况:
from dba_jobs_running;
DBA_JOBS_RUNNING各字段含义如下:
2 SID NUMBER 正在运行任务的会话ID
of process which is executing the job. See v$lock. 】
4 JOB NUMBER 正在运行任务的唯一标示号
5 【Identifier of job. This job is currently executing.】
6 FAILURES 7 【How many times has this job started 8 LAST_DATE DATE 最后一次成功运行任务的时间
9 【Date that this job last successfully executed】
10 LAST_SEC 11 【Same 12 THIS_DATE DATE 正在运行任务的开始时间,如果没有运行任务则为null
13 【Date that this job started executing (usually 14 THIS_SEC 15 【Same 16 INSTANCE 17 【Instance to run the job
3.2 JOB的失败重试
当JOB实现失败时,数据库会自动安排重新执行,此时JOB执行时间按下面情况来定: 1) 如果sysdate>=next_date,则直接执行;
2) 第i次失败,等待2i分钟后开始第i+1次数据库自动安排的重新执行,当2i>1440分钟时,时间固定为1440分钟;
3) 重试次数达16次时,JOB不再自动执行(用户还是可手动执行再失败的),标记中断标识, 3.3 停止正在运行的JOB
由于remove、broken都只是影响任务后续的执行情况,并不会对正在运行的任务造成影响,而有些情况下,由于存储过程的问题或者数据之间的影响等各种原因导致JOB执行异常,我们需要终止正在运行的异常JOB;也可能是JOB执行时间过长,人为需要停止正在运行的JOB。在这个时候我们需要按下面步骤进行处理:
** 第一步:查询JOB情况得到需要停止的JOB的编号 **from user_jobs;
from dba_jobs_running;
4
** 第二步:将需要停止的JOB标记中断,以避免停止后又运行 ** 7 dbms_job.broken(job编号,true);
10 /
11
** 第三步:查询JOB运行情况,并选择适当语句杀会话,甚至杀进程(谨慎操作) **select b.sid,-- session的id
c.serial#,-- session的序列号
d.spid,-- 操作系统进程ID16 b.job,128); line-height:1.5!important"> JOB编号
17 a.what,128); line-height:1.5!important"> 任务内容
18 b.failures,128); line-height:1.5!important"> 失败次数
19 b.this_date,128); line-height:1.5!important"> 开始时间
20 floor(sysdate - b.this_date) || 天||
21 to_char(trunc(sysdate,0); line-height:1.5!important">') + (sysdate - b.this_date),0); line-height:1.5!important">hh24:mi:ss') this_total,128); line-height:1.5!important"> 当前耗时
22 (select f.sql_fulltext
23 from v$locked_object e,v$sql f
where e.session_id = c.sid
25 and f.hash_value = c.sql_hash_value
26 and rownum 1) sql_fulltext,128); line-height:1.5!important"> 如果锁对象,则获取当前sql
27 c.inst_id,128); line-height:1.5!important"> 数据库实例ID
28 c.status,128); line-height:1.5!important">会话状态
29 alter system kill session ''' || b.sid || c.serial# 30 ''' immediate;' 普通环境杀会话,128); line-height:1.5!important"> session级杀会话
31 32 c.inst_id ' RAC环境杀会话,128); line-height:1.5!important"> RAC环境session级杀会话
33 /*
kill session语句并不实际杀死会话,只相当于让会话自我清除,在某些情况下,例如等待远程数据库应答或
35 回滚当前事务时,都会等待这些操作完成,这时就将会话状态标记为"marked for kill",数据库会尽快将它杀掉,
如果加上immediate,那么则会要求将控制权立即返回给当前会话
37 38 alter system disconnect session 39 post_transaction或immediate;' 数据库杀进程,128); line-height:1.5!important">40 41 c.inst_id ' 数据库RAC环境杀进程,128); line-height:1.5!important">42 disconnect是在数据库中从操作系统层面清除服务器进程,
44 post_transaction表示清除前需等待正在进行的事务完成,
45 而immediate则表示立即清除并回滚正在进行的事务,
46 两者必须有其一,都有时,post_transaction优先级高,忽视immediate子句。
47 用disconnect我们就不用切换到操作系统层面用下面语句去清除进程了
48 49 g.host_name ==>|| utl_inaddr.get_host_address(g.host_name) "机器==>IP",128); line-height:1.5!important"> 机器及IP
50 orakill || g.instance_name ' || d.spid "Windows杀进程",128); line-height:1.5!important">51 kill || d.spid "UnixORLinux杀进程1",128); line-height:1.5!important">52 kill -9 || d.spid "UnixORLinux杀进程2" 用1杀不掉就加-9
不管是在数据库用disconnect还是上面到操作系统上面敲kill命令,都是杀的进程,
杀掉操作系统进程是一件危险的事情,千万不得误杀,请务必谨慎操作,严格确认。
57 from user_jobs a,128); line-height:1.5!important">58 dba_jobs_running b,128); line-height:1.5!important">59 gv$session c,128); line-height:1.5!important">60 gv$process d,128); line-height:1.5!important">61 gv$instance g
62 where a.job = b.job
63 and b.sid 64 and c.paddr = d.addr
65 and g.inst_id = c.inst_id;
66
** 第四步:恢复JOB,使其继续执行 **68 如果JOB未修复好,可不执行此步操作
69 70 dbms_job.broken(job编号,false);
71 dbms_job.broken(job编号,false,可加个参数修改接来下运行的时间原默认为sysdate);
72 73 74 /
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|