DBMS_SCHEDULER is so much more flexible the DBMS_JOB and makes everything easier, some examples:
- To set up your intervals you just specify the parameter repeat_interval.
MON-FRI 22.00: repeat_interval=> 'FREQ=DAILY; BYDAY=MON,TUE,WED,THU,FRI; BYHOUR=22;'
Every hour, every day: repeat_interval => 'FREQ=HOURLY;INTERVAL=1'
Every monday, 05:00: repeat_interval=> 'FREQ=DAILY; BYDAY=MON; BYHOUR=5;' - You will not get the problem with shifting start times that you have with DBMS_JOB.
- Possible to create chains of jobs that are dependent of each other.
- Possible to schedule:
- Execution of host scripts.
- E-mail notifications.
- Execute host scripts on remote servers (requires an agent on the remote server).
- Execute jobs on multiple databases. - You can create a file watcher that will let you monitor a folder for files. When new files arrives the specified job will start.
To be able to use all the functions of DBMS_SCHEDULER you need to be on 11g release 2. There is a lot of artictles about the DBMS_SCHEDULER but you can get a good overview with examples can be found here.
One of the cooler features with the DBMS_SCHEDULER is the file watcher. I will illustrate the functionality with an exampel.
Create a new user and directory
CREATE USER fw_test_usr IDENTIFIED BY test; GRANT connect, resource, dba TO fw_test_usr; CREATE OR REPLACE DIRECTORY demo_dir AS '/home/oracle/tmp'; GRANT read, write ON DIRECTORY demo_dir TO fw_test_usr; CREATE OR REPLACE DIRECTORY demo_old_dir AS '/home/oracle/tmp/old'; GRANT read, write ON DIRECTORY demo_old_dir TO fw_test_usr;The file watchers will by default check for files every 10 minutes, we will decrease that to every minute.
CONN / AS SYSDBA BEGIN DBMS_SCHEDULER.set_attribute( 'file_watcher_schedule', 'repeat_interval', 'freq=minutely; interval=1'); END; /Now, logged in as fw_test_usr we need to set up OS privilege for file access.
BEGIN DBMS_SCHEDULER.create_credential( credential_name => 'watcher_credential', username => 'oracle', password => 'oracle'); END; SELECT * FROM dba_scheduler_credentials;The next step is to create the file watcher. The file watcher is not enabled yet (enabled => FALSE).
BEGIN DBMS_SCHEDULER.create_file_watcher( file_watcher_name => 'demo_file_watcher', directory_path => '/home/oracle/tmp', file_name => '*.txt', credential_name => 'watcher_credential', destination => NULL, enabled => FALSE); END; SELECT * FROM dba_scheduler_file_watchers;Create a table and the procedure that will be used by the file watcher.
CREATE TABLE fw_demo_tbl_output (message VARCHAR2(4000), row1 VARCHAR2(4000)); CREATE OR REPLACE PROCEDURE fw_demo_proc (p_fileinfo SYS.SCHEDULER_FILEWATCHER_RESULT) AS v_file utl_file.file_type; v_message VARCHAR2(4000); v_row1 VARCHAR2(4000); BEGIN -- file path, name and size v_message := p_fileinfo.directory_path||'/'|| p_fileinfo.actual_file_name||'('|| p_fileinfo.file_size||')'; -- read the first row of the file v_file := utl_file.fopen('DEMO_DIR', p_fileinfo.actual_file_name, 'R'); LOOP BEGIN utl_file.get_line(v_file, v_row1); EXIT; EXCEPTION WHEN OTHERS THEN EXIT; END; END LOOP; utl_file.fclose(v_file); -- move the file to the old directory with a new name utl_file.frename (src_location => 'DEMO_DIR', src_filename => p_fileinfo.actual_file_name, dest_location => 'DEMO_OLD_DIR', dest_filename => p_fileinfo.actual_file_name||'.'||to_char(SYSDATE, 'YYMMDDHH24MISS'), overwrite => FALSE); INSERT INTO fw_demo_tbl_output (message, row1) VALUES (v_message, v_row1); COMMIT; END;Create a Program object with a Metadata argument (what will happen when the file watcher event is raised). The program must reference the event_message to retrieve information about the file, such as it's name. The program is not enabled yet (enabled => FALSE).
BEGIN DBMS_SCHEDULER.create_program( program_name => 'fw_demo_prog', program_type => 'stored_procedure', program_action => 'fw_demo_proc', number_of_arguments => 1, enabled => FALSE); END; BEGIN DBMS_SCHEDULER.define_metadata_argument( program_name => 'fw_demo_prog', metadata_attribute => 'EVENT_MESSAGE', argument_position => 1); END; SELECT * FROM dba_scheduler_programs WHERE program_name= 'FW_DEMO_PROG' ORDER BY 1; SELECT * FROM dba_scheduler_program_args WHERE program_name = 'FW_DEMO_PROG';Now, create the job. The job is not enabled yet (enabled => FALSE).
BEGIN DBMS_SCHEDULER.create_job( job_name => 'fw_demo_job', program_name => 'fw_demo_prog', event_condition => NULL, queue_spec => 'demo_file_watcher', auto_drop => FALSE, enabled => FALSE); END; SELECT * FROM dba_scheduler_jobs WHERE job_name='FW_DEMO_JOB';By default, the arrival of new files will be ignored if the job is already running. If you need the job to fire for each new arrival, regardless of whether the job is already running or not, set the PARALLEL_INSTANCES attribute for the job to true. The job will then be run as a lightweight job.
BEGIN DBMS_SCHEDULER.set_attribute('fw_demo_job','parallel_instances',TRUE); END;The last step is to enable everything.
BEGIN DBMS_SCHEDULER.enable('demo_file_watcher'); DBMS_SCHEDULER.enable('fw_demo_prog'); DBMS_SCHEDULER.enable('fw_demo_job'); END;Now create some .txt files in folder /home/oracle/tmp on the server. Then wait a couple a minutes and the information sould appear in the table. The files should also have been moved to the old folder on the server.
SELECT * FROM fw_demo_tbl_output;
No comments:
Post a Comment