一、dbms_job维护作业
作业有4个要素:
①作业号:系统自动发生
②做什么:我们来指定,分号分隔语句,可以是存储过程
③开始时间:date类型
④间隔时间:varchar2类型
写一个简单的作业: -----如果你忘了怎么写了,没关系,可以去看rdbms/spauto这个文件,是系统创建整点快照的作业
variable jobno number
begin
dbms_job.submit(:jobno,'update scott.t1 set sal=sal+1;commit;',sysdate,'sysdate+1/24/60');
commit;
end;
/
col error clear
select * from v$bgprocess where paddr<>'00';
--CJQ0 (Job Queue Coordinator) 作业队列调度后台进程
--同时最大的作业数
show parameter JOB_QUEUE_PROCESSES
ALTER SYSTEM set job_queue_processes=20;
--查看作业
select * from dba_jobs;
select job,what from dba_jobs;
--作业号有sys.jobseq 序列产生
select * from dba_sequences where sequence_name='JOBSEQ';
--修改作业
1、修改调度时间
select job,what from dba_jobs
begin
dbms_job.change(6,null,null,'sysdate+3');
end;
/
2、修改下次启用时间
begin
dbms_job.next_date(6,sysdate+1/24/60);
end;
/
3、作业运行后不再启用
begin
dbms_job.interval(6,'null');
end;
/
4、修改作业的内容
begin
dbms_job.what(6,'update scott.emp set sal=sal+10;');
end;
/
5、中断作业
BEGIN
DBMS_JOB.BROKEN(27, TRUE);
END;
/
select job,LAST_DATE,LAST_SEC,NEXT_DATE, NEXT_SEC,INTERVAL, BROKEN,FAILURES from dba_jobs;
6、启用作业
BEGIN
DBMS_JOB.BROKEN(24, FALSE, NEXT_DAY(SYSDATE, 'MONDAY'));
END;
/
select job,LAST_DATE,LAST_SEC,NEXT_DATE, NEXT_SEC,INTERVAL, BROKEN,FAILURES from dba_jobs;
7、运行作业
exec DBMS_JOB.RUN(28);
8、删除作业
select job,name from dba_jobs;
execute dbms_job.remove(27);
---------------------------------------------------------------------------------------------------------------------------------------------------------------
dbms_scheduler 的运用 ----10g新特性
dbms_job 有两个缺点:1、时间间隔的控制不灵活,时间不一的间隔 2、不能调用操作系统的脚本
看一下数据库自己带的调度作业吧:
select JOB_NAME,PROGRAM_NAME,REPEAT_INTERVAL,SCHEDULE_NAME from dba_scheduler_jobs;
JOB_NAME PROGRAM_NAME REPEAT_INTERVAL SCHEDULE_NAME
------------------------------ ------------------------- --------------------------------------------- -------------------------
AUTO_SPACE_ADVISOR_JOB AUTO_SPACE_ADVISOR_PROG MAINTENANCE_WINDOW_GROUP
GATHER_STATS_JOB GATHER_STATS_PROG MAINTENANCE_WINDOW_GROUP
FGR$AUTOPURGE_JOB freq=daily;byhour=0;byminute=0;bysecond=0
PURGE_LOG PURGE_LOG_PROG DAILY_PURGE_SCHEDULE
RLM$SCHDNEGACTION FREQ=MINUTELY;INTERVAL=60
RLM$EVTCLEANUP FREQ = HOURLY; INTERVAL = 1
6 rows selected.
观察上面的结果,我们会发现有时间间隔的没有调度名称, 有调度名称就没有时间间隔
这里的调度(scheduler)不要和我们常说的调度作业混淆~!
它就是一个时间间隔的策略
我们可以用DBMS_SCHEDULER.CREATE_SCHEDULE()来创建我们想要的调度,比如我创建一个名字叫MYTEST_SCHEDULE 的调度,每天4:00 执行.
Begin
dbms_scheduler.create_schedule(
repeat_interval => 'FREQ=DAILY;BYHOUR=4;BYMINUTE=0;BYSECOND=0',
start_date => systimestamp at time zone 'PRC',
comments => '---this is my test schedule---',
schedule_name => 'MYTEST_SCHEDULE');
end;
/
我们可以通过dba_scheduler_schedules来看系统中有什么调度
我们看看DAILY_PURGE_SCHEDULE这个调度
select schedule_name,repeat_interval from dba_scheduler_schedules where schedule_name='DAILY_PURGE_SCHEDULE';
SCHEDULE_NAME REPEAT_INTERVAL
------------------------- ---------------------------------------------
DAILY_PURGE_SCHEDULE freq=daily;byhour=3;byminute=0;bysecond=0
收集统计信息的作业(GATHER_STATS_JOB)的调度:MAINTENANCE_WINDOW_GROUP是窗口组
SQL> select * from DBA_SCHEDULER_WINGROUP_MEMBERS;
WINDOW_GROUP_NAME WINDOW_NAME
------------------------------ -------------------
MAINTENANCE_WINDOW_GROUP WEEKNIGHT_WINDOW
MAINTENANCE_WINDOW_GROUP WEEKEND_WINDOW
从上面我们看到维护窗口组(MAINTENANCE_WINDOW_GROUP)中有两个窗口~!
SQL> SELECT WINDOW_NAME,REPEAT_INTERVAL FROM DBA_SCHEDULER_WINDOWS;
WINDOW_NAME REPEAT_INTERVAL
-------------------- ---------------------------------------------------------------------
WEEKNIGHT_WINDOW freq=daily;byday=MON,TUE,WED,THU,FRI;byhour=22;byminute=0; bysecond=0
WEEKEND_WINDOW freq=daily;byday=SAT;byhour=0;byminute=0;bysecond=0
周1到周5每天晚上22点运行,周六0点运行
这样我们就明白了其实窗口(windows)和上面的调度一样,只不过比调度更NB点,窗口可以调用调度,具有资源计划限制功能,而且窗口可以组成窗口组,然后运用窗口组我们就可以更灵活的控制时间间隔了
可以使用DBMS_SCHEDULER.CREATE_WINDOW来创建一个窗口.
例如我创建了一个名为mytest_windows_1 的窗口,采用DAILY_PURGE_SCHEDULE 的调度
方式,资源计划限制方案为 SYSTEM_PLAN,持续时间为4 小时.
BEGIN
DBMS_SCHEDULER.CREATE_WINDOW(
window_name=>'mytest_windows_1',
resource_plan=>'SYSTEM_PLAN',
schedule_name=>'SYS.DAILY_PURGE_SCHEDULE',
duration=>numtodsinterval(240, 'minute'),
window_priority=>'LOW',
comments=>'');
END;
/
然后我们可以使用DBMS_SCHEDULER.CREATE_WINDOW_GROUP来创建一个窗口组:
BEGIN
DBMS_SCHEDULER.CREATE_WINDOW_GROUP(
group_name=>'mytest_window_group',
window_list=>'MYTEST_WINDOWS_1,WEEKEND_WINDOW');
END;
/
*******************************************************************************************************
以上说的都是调度作业的时间间隔问题,下面说一说调度作业的内容
*******************************************************************************************************
也就是上面select JOB_NAME,PROGRAM_NAME,REPEAT_INTERVAL,SCHEDULE_NAME from dba_scheduler_jobs;查询中红色对应的部分
我们来看看GATHER_STATS_PROG这个program
SQL> select PROGRAM_ACTION from DBA_SCHEDULER_PROGRAMS where PROGRAM_NAME='GATHER_STATS_PROG';
PROGRAM_ACTION
---------------------------------------------------------------------
dbms_stats.gather_database_stats_job_proc
其实这个程序就是调用了一个存储过程!
那我们整体看一下GATHER_STATS_JOB这个调度作业做了什么:她就是在MAINTENANCE_WINDOW_GROUP这个窗口组的时间内运行GATHER_STATS_PROG这个程序,而这个程序调用的是dbms_stats.gather_database_stats_job_proc这个存储过程~!
调度作业中还有两个概念:链(chain)和作业类(job_class)
链就是将一个/几个program/event 放到一起依次执行
作业类就是定义了运行作业的资源使用者组.通过使用窗口中的资源计划,我们可以在不同资源组
和不同作业类之间分配资源.
好了好了,我们总结一下dbms_scheduler
1、作业(job) ---dbms_scheduler.create_job
2、调度(scheduler) ---dbms_scheduler.create_schedule
3、窗口(window) ---DBMS_SCHEDULER.CREATE_WINDOW
4、窗口组(window_group) ---DBMS_SCHEDULER.CREATE_WINDOW_GROUP
5、程序(program) ---DBMS_SCHEDULER.CREATE_PROGRAM
6、链(chain) ---dbms_scheduler.create_chain
7、作业类(job_class) ---dbms_scheduler.create_job_class
弄清楚这些概念之间的关系
dba_scheduler_jobs ---调度作业的主字典
dba_scheduler_schedules ---调度字典
dba_scheduler_wingroup_members ----窗口组中有哪些窗口
dba_scheduler_windows ----窗口字典
dba_scheduler_programs ---程序字典
了解以上这些字典
其实上面说了这么多,就是让你更深刻的理解scheduler job 这个东西
我们运用中其实不用这么多花里胡哨的东西~!这些不是必须的。我们可以直接留作业,和以前dbms_job 一样,而且可以运行操作系统的
脚本。
begin
dbms_scheduler.create_job
(
job_name => 'ARC_MOVE',
repeat_interval => 'FREQ=MINUTELY; INTERVAL=30',
job_type => 'EXECUTABLE',
job_action => '/home/dbtools/move_arcs.sh',
enabled => true,
comments => 'Move Archived Logs to a Different Directory'
);
end;
/
以上这个调度作业:我们并没用到调度、窗口、程序!
————————————————————————————————————————————————————————————————
**补充:
select JOB_NAME,PROGRAM_NAME,REPEAT_INTERVAL,SCHEDULE_NAME from dba_scheduler_jobs;
JOB_NAME PROGRAM_NAME REPEAT_INTERVAL SCHEDULE_NAME
------------------------------ ------------------------- --------------------------------------------- -------------------------
AUTO_SPACE_ADVISOR_JOB AUTO_SPACE_ADVISOR_PROG MAINTENANCE_WINDOW_GROUP
GATHER_STATS_JOB GATHER_STATS_PROG MAINTENANCE_WINDOW_GROUP
FGR$AUTOPURGE_JOB freq=daily;byhour=0;byminute=0;bysecond=0
PURGE_LOG PURGE_LOG_PROG DAILY_PURGE_SCHEDULE
RLM$SCHDNEGACTION FREQ=MINUTELY;INTERVAL=60
RLM$EVTCLEANUP FREQ = HOURLY; INTERVAL = 1
gather_stats_job这个调度任务调用gather_stats_prog这个程序,这个程序跑的是一个存储过程:dbms_stats.gather_database_stats_job_proc执行信息收集,它会检测哪些对象没有统计信息或者统计信息比较陈旧,将优先对这些对象进行分析。而我们平时手工用的dbms_stats.gather_database_stats,是没有分优先级的,也就是它将对数据里的所有对象进行分析,不管该对象有没有被分析过。
dbms_stats.gather_database_stats_job_proc挑选分析的对象有两个条件:
1、对象之前从未收集过统计信息,或由于某些原因没有统计信息
2、对象的统计信息相对陈旧(stale),是否陈旧的评判标准是由上次收集信息到此次收集期间被修改过的行数超过10% (oracle通过查询dba_tab_modifications)