使用job模拟定时从元数据表中抽取指定数据进入目标表的过程。
一、创建元数据表
–create table test_origianl
create table test_original_data(
id number(10,2) primary key,
name varchar2(200),
descCont varchar2(100),
dateType char(5)
);
二、元数据表中插入数据
insert into test_original_data values(2.9,‘name1’,‘desc1’,‘int’);
insert into test_original_data values(3.0,‘name2’,‘desc2’,‘long’);
insert into test_original_data values(2.8,‘name3’,‘desc3’,‘float’);
insert into test_original_data values(2.6,‘name4’,‘desc4’,‘do’);
insert into test_original_data values(2.1,‘name223’,‘desc33’,‘float’);
insert into test_original_data values(5.12,‘name22r34’,‘desc3r34’,‘float’);
三、提交事务
commit;
四、创建目标表
—create table
为保持与元数据表相同的表结构,使得元数据表中的记录可以不做任何修改直接插入目标表中,采用CTAS的方式创建目标表。
create table test_destination_dat
as
select * from test_original_data where 1!=1;
只创建相同的表结构,不导入元数据表中的记录。
五、提交事务
commit;
六、创建定时被调用的存储过程
---- create procedure
create or replace procedure job_test_pro
authid current_user
as
begin
–先truncate table清空原来的数据,重新把符号条件的数据导入(此处使用truncate在大数据量的情况下戏剧化的提高效率)
execute immediate ‘truncate table test_destination_dat’;
insert into test_destination_dat (select * from test_original_data where dateType=‘float’ );
exception
when others then
dbms_output.put_line(‘errorMsg’||SQLERRM||‘errorCode’||SQLCODE);
end job_test_pro;
注:1、在存储过程中一般是没有create table 、truncate table的权限的。如果在存储过程中直接使用语句truncate table test_destination_dat会报错,不能执行该语 句。 在存储过程一般是不能直接使用create table,truncate table这类似的语句的,如果要使用这些语句必须使用excute immediate + 所要执行的sql语句来实现。
2、Authid Current_User:
这个语句比较重要,如果我们在创建存储过程的时候不添加这条语句执行该存储过程将不会成功,原因是默认情况存储过程是没有Create table,truncate table等 权限的,即使当前用户有DBA的权限也不行,如果存储过程中存在创建表、截断表的操作,可以有以下两种方式来解决该问题。
(1) 显示的赋予该用户Create table的权限,grant create table to user.
(2) 在存储过程中使用Authid Current_User 标识使用当前用户的权限。
七、创建job
1、定义job名称
variable job2014 number —定义在oracle中自动生成job的序号的数据类型对应到dba_jobs的数据字典中的字段job的值。现在job值为41对应名称为job2014数 据类型为number
2、将job注册到dba_jobs表中定时启动job调用存储过程
begin
dbms_job.submit(:job2014,‘JOB_TEST_PRO;’,sysdate,‘sysdate+1/1440’);
end;
/
commit;
注意:dbms_job.submit()方法的定义如下
sys.dbms_job.submit(job => :jobno,
what => ‘myProc;myProcs;myProcss(’‘测试’’);’,//用分号将多个存储过程分开,有参数的话直接写就可以了
next_date => to_date(‘07-04-2011 22:00:00’, ‘dd-mm-yyyy hh24:mi:ss’),
interval => ‘sysdate+1’);
1、这里需要注意的是,在submit方法的前面一定要先定义job这个变量
2、submit方法的第二个参数是一个存储过程的名,记得在后面添加“;”号
3、在next_date是一个时间类型变量而不是一个字符串,所以需要注意不要把它当成字符串,不需要对该参数加引号
4、最后一个参数interval是一个字符串类型,记得添加引号
5、第一个参数格式为:jobno,目的是绑定job和存储过程。
6、最常见的错误如下所示:ORA-01008: not all variables bound就是没有定义变量的意思。一定记的在使用submit方法时定义jobno变量。
7、下面是常有的设置Interval的方法:
每天固定时间运行,比如早上8点:Trunc(Sysdate+1) + 8/24
每天:trunc(sysdate+1)
每周:trunc(sysdate+7)
每月:trunc(sysdate+30)
每个星期日:next_day(trunc(sysdate),’SUNDAY’)
每天6点:trunc(sysdate+1)+6/24
半个小时:sysdate+30/1440
8、声明变量和绑定job变量到存储过程并注册到dba_jobs表中必须在sqlplus下执行,在plsqldevloper中不能成功运行。
八、job异常情况处理
JOB不能运行情况处理
1.先来了解一下JOB的参数说明:与job相关的参数一个是job_queue_processes,这个是运行JOB时候所起的进程数,当然系统里面JOB大于这个数值后,就会有排 队等候的,最小值是0,表示不运行JOB,最大值是36,在OS上对应的进程时SNPn,9i以后OS上管理JOB的进程叫CJQn.可以使用下面这个SQL确定目前有几个SNP/C JQ在运行。
select * from v
b
g
p
r
o
c
e
s
s
,
这
个
p
a
d
d
r
不
为
空
的
s
n
p
/
c
j
q
进
程
就
是
目
前
空
闲
的
进
程
,
有
的
表
示
正
在
工
作
的
进
程
。
另
外
一
个
是
j
o
b
q
u
e
u
e
i
n
t
e
r
v
a
l
,
范
围
在
1
—
—
3600
之
间
,
单
位
是
秒
,
这
个
是
唤
醒
J
O
B
的
p
r
o
c
e
s
s
,
因
为
每
次
s
n
p
运
行
完
他
就
休
息
了
,
需
要
定
期
唤
醒
他
,
这
个
值
不
能
太
小
,
太
小
会
影
响
数
据
库
的
性
能
。
2.
诊
断
:
先
确
定
上
面
这
两
个
参
数
设
置
是
否
正
确
,
特
别
是
第
一
个
参
数
,
设
置
为
0
了
,
所
有
J
O
B
就
不
会
跑
,
确
认
无
误
后
,
我
们
继
续
向
下
。
3.
使
用
下
面
的
S
Q
L
察
看
J
O
B
的
的
b
r
o
k
e
n
,
l
a
s
t
d
a
t
e
和
n
e
x
t
d
a
t
e
,
l
a
s
t
d
a
t
e
是
指
最
近
一
次
j
o
b
运
行
成
功
的
结
束
时
间
,
n
e
x
t
d
a
t
e
是
根
据
设
置
的
频
率
计
算
的
下
次
执
行
时
间
,
根
据
这
个
信
息
就
可
以
判
断
J
O
B
上
次
是
否
正
常
,
还
可
以
判
断
下
次
的
时
间
对
不
对
,
S
Q
L
如
下
:
s
e
l
e
c
t
∗
f
r
o
m
d
b
a
j
o
b
s
有
时
候
我
们
发
现
他
的
n
e
x
t
d
a
t
e
是
4000
年
1
月
1
日
,
说
明
j
o
b
要
不
就
是
在
r
u
n
n
i
n
g
,
要
不
就
是
状
态
是
b
r
e
a
k
(
b
r
o
k
e
n
=
Y
)
,
如
果
发
现
J
O
B
的
b
r
o
k
e
n
值
为
Y
,
找
用
户
了
解
一
下
,
确
定
该
J
O
B
是
否
可
以
b
r
o
k
e
n
,
如
果
不
能
b
r
o
k
e
n
,
那
就
把
b
r
o
k
e
n
值
修
改
成
N
,
修
改
再
使
用
上
面
的
S
Q
L
察
看
就
发
现
他
的
l
a
s
t
d
a
t
e
已
经
变
了
,
J
O
B
即
可
正
常
运
行
,
修
改
b
r
o
k
e
n
状
态
的
S
Q
L
如
下
:
d
e
c
l
a
r
e
B
E
G
I
N
D
B
M
S
J
O
B
.
B
R
O
K
E
N
(
<
J
O
B
I
D
>
,
F
A
L
S
E
)
;
E
N
D
;
4.
使
用
下
面
的
S
Q
L
查
询
是
否
J
O
B
还
在
R
u
n
n
i
n
g
s
e
l
e
c
t
∗
f
r
o
m
d
b
a
j
o
b
s
r
u
n
n
i
n
g
如
果
发
现
J
O
B
已
经
R
u
n
了
很
久
了
还
没
有
结
束
,
就
要
查
原
因
了
。
一
般
的
J
O
B
r
u
n
n
i
n
g
时
会
锁
定
相
关
的
相
关
的
资
源
,
可
以
查
看
一
下
v
bgprocess,这个paddr不为空的snp/cjq进程就是目前空闲的进程,有的表示正在工作的进程。 另外一个是job_queue_interval,范围在1——3600之间,单位是秒,这个是唤醒JOB的process,因为每次snp运行完他就休息了,需要定期唤醒他,这个值不能 太小,太小会影响数据库的性能。 2.诊断:先确定上面这两个参数设置是否正确,特别是第一个参数,设置为0了,所有JOB就不会跑,确认无误后,我们继续向下。 3.使用下面的SQL察看JOB的的broken,last_date和next_date,last_date是指最近一次job运行成功的结束时间,next_date是根据设置的频率计算的下次执行 时间,根据这个信息就可以判断JOB上次是否正常,还可以判断下次的时间对不对,SQL如下: select * from dba_jobs 有时候我们发现他的next_date是4000年1月1日,说明job要不就是在running,要不就是状态是break(broken=Y),如果发现JOB的broken值为Y,找用户了解 一下,确定该JOB是否可以broken,如果不能broken,那就把broken值修改成N,修改再使用上面的SQL察看就发现他的last_date已经变了,JOB即可正常运行, 修改broken状态的SQL如下: declare BEGIN DBMS_JOB.BROKEN(<JOB_ID>,FALSE); END; 4.使用下面的SQL查询是否JOB还在Running select * from dba_jobs_running 如果发现JOB已经Run了很久了还没有结束,就要查原因了。一般的JOB running时会锁定相关的相关的资源,可以查看一下v
bgprocess,这个paddr不为空的snp/cjq进程就是目前空闲的进程,有的表示正在工作的进程。 另外一个是jobqueueinterval,范围在1——3600之间,单位是秒,这个是唤醒JOB的process,因为每次snp运行完他就休息了,需要定期唤醒他,这个值不能 太小,太小会影响数据库的性能。 2.诊断:先确定上面这两个参数设置是否正确,特别是第一个参数,设置为0了,所有JOB就不会跑,确认无误后,我们继续向下。 3.使用下面的SQL察看JOB的的broken,lastdate和nextdate,lastdate是指最近一次job运行成功的结束时间,nextdate是根据设置的频率计算的下次执行 时间,根据这个信息就可以判断JOB上次是否正常,还可以判断下次的时间对不对,SQL如下: select∗fromdbajobs 有时候我们发现他的nextdate是4000年1月1日,说明job要不就是在running,要不就是状态是break(broken=Y),如果发现JOB的broken值为Y,找用户了解 一下,确定该JOB是否可以broken,如果不能broken,那就把broken值修改成N,修改再使用上面的SQL察看就发现他的lastdate已经变了,JOB即可正常运行, 修改broken状态的SQL如下: declare BEGIN DBMSJOB.BROKEN(<JOBID>,FALSE); END; 4.使用下面的SQL查询是否JOB还在Running select∗fromdbajobsrunning 如果发现JOB已经Run了很久了还没有结束,就要查原因了。一般的JOBrunning时会锁定相关的相关的资源,可以查看一下vaccess和v$locked_object这两个v iew,如果发现其他进程锁定了与JOB相关的Object,包括PKG/Function/Procedure/Table等资源,那么就要把其他进程删除,有必要的话,把JOB的进程也删除 ,再重新跑看看结果。
5.如果上面都正常,但是JOB还不run,怎么办?那我们要考虑把JOB进程重启一次,防止是SNP进程死了造成JOB不跑,指令如下:
alter system set job_queue_processes=0 ——关闭job进程,等待5——10秒钟
alter system set job_quene_processes=5 ——恢复原来的值
九、手动运行job的指令
begin
dbms_job.run(:job2014);
end;
/
十、删除job
begin
dbms_job.remove(:job2014);
end;
/
十一、查看job相关视图及各字段的注解
select job,last_date,last_sec,broken,failures,interval, what from dba_jobs
详解 dba_jobs中几个比较重要的字段
job: 指的是job的id号。比如上面的 41
failures:job执行的时候失败次数,如果超过了15次,那么broken列将被标为Y,以后就不会运行该job了
broken:默认为N,如果为Y,意味着不再执行该job!
interval:执行job的间隔时间。
what:该job的实际工作。
总结:模拟定时从元数据表中抽取指定类型的数据添加到目标表中,用定时job调用存储过程。
未来已来,将至已至。
如果你觉得本篇文章对你有所帮助,请支持作者哦