DBMS_JOB是一个可以用来调度任务的PL/SQL程序包,现在已经逐渐被Oracle Scheduler所替代,后者的功能更为强大,应用也更为灵活。Oracle建议大家尽量使用Oracle Scheduler来代替DBMS_JOB,尽管如此,考虑到兼容性,Oracle 11g还是提供了对DBMS_JOB包的支持。
一、 简单用法
Create a job
BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'my_java_job', job_type => 'EXECUTABLE', job_action => '/usr/bin/java myClass', repeat_interval => 'FREQ=MINUTELY', enabled => TRUE ); END; /
Unlike DBMS_JOB you do not need to commit the job creation for it to be taken into account. As a corollary, if you want to cancel it, you have to remove or disable it (see below).
Remove a job
EXEC DBMS_SCHEDULER.DROP_JOB('my_java_job');
Run a job now
To force immediate job execution:
EXEC dbms_scheduler.run_job('myjob');
Change job attributes
Examples:
EXEC DBMS_SCHEDULER.SET_ATTRIBUTE('WEEKNIGHT_WINDOW', 'duration', '+000 06:00:00');
BEGIN DBMS_SCHEDULER.SET_ATTRIBUTE ('WEEKNIGHT_WINDOW', 'repeat_interval', 'freq=daily;byday=MON, TUE, WED, THU, FRI;byhour=0;byminute=0;bysecond=0'); END;
Enable / Disable a job
BEGIN DBMS_SCHEDULER.ENABLE('myjob'); END;
BEGIN DBMS_SCHEDULER.DISABLE('myjob'); END;
Monitoring jobs
SELECT * FROM dba_scheduler_jobs WHERE job_name = 'MY_JAVA_JOB'; SELECT * FROM dba_scheduler_job_log WHERE job_name = 'MY_JAVA_JOB';
or checking from JOB owner schema
SELECT * FROM user_scheduler_jobs WHERE job_name = 'MY_JAVA_JOB'; SELECT * FROM user_scheduler_job_log WHERE job_name = 'MY_JAVA_JOB';
Use user_scheduler_jobs and user_scheduler_job_log to only see jobs that belong to your user (current schema).
二、 DBMS_SCHEDULER vs DBMS_JOB
DBMS_SCHEDULER includes the following features that DBMS_JOB does not have :
- logging of job runs (job history)
- simple but powerful scheduling syntax (similar to but more powerful than cron syntax)
- running of jobs outside of the database on the operating system
- resource management between different classes of jobs
- use of job arguments including passing of objects into stored procedures
- privilege-based security model for jobs
- naming of jobs and comments in jobs
- stored, reusable schedules
Features in releases after 10g Release 1 include :
- dependencies between job units (10gR2 and up)
- scheduling based on financial calendars and fiscal quarters (10gR2 and up)
- event based jobs which run when an event is received (10gR2 and up)
- running of jobs on remote machines (11gR1 and up)
- e-mail notifications on job events of interest (10gR2 and up)
- starting a job based on arrival of a file (10gR2 and up)
三、 如何查看Scheduler DDL语句
对于普通用户
select dbms_metadata.get_ddl(‘PROCOBJ’,’JOB_NAME’,’JOB_OWNER’) from dual;
set pagesize 299
set long 999
select dbms_metadata.get_ddl('PROCOBJ','DBACLASS_PURGE','DBAUSER') from dual;
DBMS_METADATA.GET_DDL('PROCOBJ','DBACLASS_PURGE','DBAUSER')
--------------------------------------------------------------------------------
BEGIN
dbms_scheduler.create_job('"DBACLASS_PURGE"',
job_type=>'STORED_PROCEDURE', job_action=>
'DBAUSER.DBA_CREATE_DBACIRCUIT_PATH'
, number_of_arguments=>0,
start_date=>TO_TIMESTAMP_TZ('06-JUN-2017 06.58.16.001208000 AM ASIA/BAHRAIN','DD
-MON-RRRR HH.MI.SSXFF AM TZR','NLS_DATE_LANGUAGE=english'), repeat_interval=>
'FREQ=HOURLY;INTERVAL=2;'
, end_date=>NULL,
job_class=>'"DEFAULT_JOB_CLASS"', enabled=>FALSE, auto_drop=>FALSE,comments=>
'DBACLASS_PURGE'
);
dbms_scheduler.enable('"DBACLASS_PURGE"');
COMMIT;
END;
然而对于sys用户,上面的查询就会报错
select dbms_metadata.get_ddl('PROCOBJ','CLEANUP_ONLINE_IND_BUILD','SYS') from dual;
ERROR:
ORA-31603: object "CLEANUP_ONLINE_IND_BUILD" of type PROCOBJ not found in schema "SYS"
ORA-06512: at "SYS.DBMS_METADATA", line 6069
ORA-06512: at "SYS.DBMS_METADATA", line 8666
ORA-06512: at line 1
no rows selected
一个workaround 是将 scheduler job 拷贝到另一个用户下
SQL> select owner,job_name from dba_scheduler_jobs where job_name='CLEANUP_ONLINE_IND_BUILD';
OWNER JOB_NAME
------------ ----------------------------------
SYS CLEANUP_ONLINE_IND_BUILD
SQL> exec dbms_scheduler.copy_job('SYS.CLEANUP_ONLINE_IND_BUILD','DBACLASS.CLEANUP_ONLINE_IND_BUILD');
PL/SQL procedure successfully completed.
SQL> select owner,job_name from dba_scheduler_jobs where job_name='CLEANUP_ONLINE_IND_BUILD';
OWNER JOB_NAME
------------ ----------------------------------
SYS CLEANUP_ONLINE_IND_BUILD
DBACLASS CLEANUP_ONLINE_IND_BUILD -- >> another copy of that job
Now we have the sImilar job under the user DBACLASS, so we can get the DDL without any error.
select dbms_metadata.get_ddl('PROCOBJ','CLEANUP_ONLINE_IND_BUILD','BSSDBA') from dual;
DBMS_METADATA.GET_DDL('PROCOBJ','CLEANUP_ONLINE_IND_BUILD','BSSDBA')
--------------------------------------------------------------------------------
BEGIN
dbms_scheduler.create_job('"CLEANUP_ONLINE_IND_BUILD"',
job_type=>'PLSQL_BLOCK', job_action=>
'declare
myinterval number;
begin
myinterval := dbms_pdb.cleanup_task(2);
if myinterval <> 0 then
next_date := systimestamp +
numtodsinterval(myinterval, ''second'');
end if;
end;'
, number_of_arguments=>0,
start_date=>TO_TIMESTAMP_TZ('07-JUL-2014 05.53.58.299360000 AM -07:00','DD-MON-R
RRR HH.MI.SSXFF AM TZR','NLS_DATE_LANGUAGE=english'), repeat_interval=>
'FREQ = HOURLY; INTERVAL = 1'
, end_date=>NULL,
job_class=>'"SCHED$_LOG_ON_ERRORS_CLASS"', enabled=>FALSE, auto_drop=>TRUE,comme
nts=>
'Cleanup Online Index Build'
);
COMMIT;
END;
参考
http://www.orafaq.com/wiki/DBMS_SCHEDULER
https://dbaclass.com/article/get-ddl-dbms-scheduler-job/