TIP It is not possible to create lightweight jobs with Database Control; the option is not visible in any of the windows.. Using Classes, Windows, and the Resource Manager The more adva
Trang 1To create a job, select the Jobs link The initial window (shown in Figure 22-5) assumes that the job is a PL/SQL block Select the CHANGE COMMAND TYPE button to nominate your program The Schedule link lets you tie the job to a precreated schedule, rather than defining the schedule within the job Note that Database Control by default reverses the values for ENABLED and AUTO DROP from the actual defaults
TIP Programs share the same namespace as jobs: you cannot have a program
with the same name as a job The same is true for schedules and windows
It is also possible to run a job independently of a schedule, by using the RUN_JOB procedure:
Figure 22-4 Creating a schedule with Database Control
Trang 2Event-Driven Jobs
The event that launches an event-driven job takes the form of a message delivered to a
queue The Oracle Database’s Advanced Queuing facility is a means for managing the
asynchronous delivery of messages The queue exists within a table, one column of
which is a user-defined object that carries the payload of the message; the other columns
are used by the Advanced Queuing control structures The flow is that a process (or
possibly several processes) should place messages on the queue The Scheduler will
monitor the queue and, depending on the content of messages, launch particular jobs
A full treatment of this is beyond the scope of the OCP examinations, but an
appreciation of how an event can launch a job is required This is a summary of the
steps with examples of the necessary code to implement a job that will run when a
file has been delivered:
1 Create an abstract data type to define the events:
Figure 22-5 Creating a job with Database Control
Trang 35 Start the queue:
exec dbms_aqadm.start_queue(queue_name=>'incoming_q');
6 Create a job that will monitor the queue and run when a certain event is enqueued:
exec dbms_scheduler.create_job(-job_name => 'load_data',-job_type => 'stored_procedure',-job_action => 'read_file',-start_date => systimestamp,-queue_spec => 'incoming_q,inc_agent',-event_condition => 'tab.user_data.event_type=1',-enabled => true);
7 Include code in the event generating application(s) to enqueue messages:
declare enqueue_options dbms_aq.enqueue_options_t;
message_properties dbms_aq.message_properties_t;
msgid raw(16);
payload incoming_t;
begin payload := incoming_t(1);
dbms_aq.enqueue(queue_name => 'incoming_q', enqueue_options => enqueue_options,
message_properties => message_properties, payload => payload,
msgid => msgid);
commit;
end;
8 Confirm that the job was launched:
select actual_start_date,status from dba_scheduler_job_run_details where job_name='LOAD_DATA';
This very simple example is intended to illustrate a mechanism whereby the arrival
of a file could trigger the running of a job The code in Step 7 would be executed by the process that generates, or detects, the file: it enqueues a message with the value
of the payload’s single attribute set to 1 This value will be checked by the Scheduler, which will then run the LOAD_DATA job
Trang 4Job Chains
A chain represents a set of linked programs with execution dependencies The steps to
follow to use job chains are
1 Create a chain object
2 Define the steps (the individual programs) of the chain
3 Define the rules connecting the steps
4 Enable the chain
5 Create a job to launch the chain
This code fragment demonstrates the first four steps:
exec dbms_scheduler.create_chain(chain_name=>'mychain');
exec dbms_scheduler.define_chain_step(chain_name =>
'mychain',-step_name => 'step1',program_name => 'prg1');
exec dbms_scheduler.define_chain_step(chain_name =>
'mychain',-step_name => 'step2',program_name => 'prg2');
exec dbms_scheduler.define_chain_step(chain_name =>
'mychain',-step_name => 'step3',program_name => 'prg3');
exec dbms_scheduler.define_chain_rule(chain_name =>
'mychain',-rule_name => 'rule1',condition => 'step1
succeeded',-action => 'start step2');
exec dbms_scheduler.define_chain_rule(chain_name =>
'mychain',-rule_name => 'rule2',condition => 'step1
failed',-action => 'start step3');
exec dbms_scheduler.enable('mychain');
These commands create and enable a very simple chain of three steps The
execution of either the second or third step is dependent on the outcome of the first
step The syntax for creating rules permits the use of keywords such as SUCCEEDED
and FAILED, which will test the outcome of another step Figure 22-6 shows the result
of running the preceding code, as seen through Database Control
To launch the chain, you must create a job This could be based on a schedule, or
an event This job will run the chain on the last Tuesday of alternate months:
exec
dbms_scheduler.create_job(job_name=>'run_mychain',-
job_type=>'chain',job_action=>'mychain',-
start_date=>next_day(last_day(sysdate)-7,'tuesday'),-
repeat_interval=>'freq=monthly;interval=2',-enabled=>true);
Lightweight Jobs
Creating and launching a job involves a certain amount of activity within the data
dictionary This may make it impossible to create a large number (perhaps hundreds)
of jobs in a short time (perhaps a few seconds) To get around this problem, it is
possible to create lightweight jobs A lightweight job is a simpler construct than a regular
job It must be based on a program, and can have only a limited range of attributes:
for example, AUTO_DROP is always TRUE A lightweight job can be created individually,
but there is little value in this The real value comes with the ability to create an array
of job definitions (perhaps hundreds) and submit them all simultaneously
Trang 5TIP It is not possible to create lightweight jobs with Database Control; the
option is not visible in any of the windows You must therefore use the DBMS_ SCHEDULER API
To create a single lightweight job, use a version of the CREATE_JOB procedure call that specifies a program and set the JOB_STYLE argument to LIGHTWEIGHT For example:
SQL> exec
dbms_scheduler.create_job(-> job_name=dbms_scheduler.create_job(->'lw21',program_name=dbms_scheduler.create_job(->'prg1',-
job_name=>'lw21',program_name=>'prg1',-> enabled=job_name=>'lw21',program_name=>'prg1',->true,job_style=job_name=>'lw21',program_name=>'prg1',->'lightweight',-
enabled=>true,job_style=>'lightweight',-> end_date=enabled=>true,job_style=>'lightweight',->to_timestamp(sysdate+1),repeat_interval=enabled=>true,job_style=>'lightweight',->'freq=hourly');
This will create a lightweight job that will run the program PRG1 every hour for the next 24 hours
Study the code in Figure 22-7, which creates and executes an array of 100
lightweight jobs
Figure 22-6 A job chain, created in the schema JON
Trang 6The following table describes each line in the anonymous PL/SQL block in
Figure 22-7
Line 2 Define a variable named LW_JOB of type SYS.JOB.
Line 3 Define an array of LW_JOBs.
Line 4 Begin the executable code.
Line 5 Initialize the array using the SYS.JOB_ARRAY function.
Line 6 Extend the array to 100 elements.
Line 7 Open a loop, to be iterated 100 times.
Lines 8 & 9 Populate the LW_JOB variable with values that will create an enabled
lightweight job named by the loop counter and using the program PRG1.
Line 10 Insert the new job into the array.
Line 11 Close the loop.
Line 12 Create all the jobs defined in the array, in a single transaction.
Line 13 End the executable code.
Line 14 Run anonymous block.
Figure 22-7 Creating lightweight jobs with the PL/SQL API
Trang 7TIP When would you use lightweight jobs? Perhaps to parallelize a business
operation consisting of many distinct tasks After changing your web sales price list, for example, you may need to refresh a vast number of web pages cached on your application server As each would be identified with a different URL, you would have to send many distinct messages You would want to send them in as short a time as possible
Using Classes, Windows,
and the Resource Manager
The more advanced capabilities of the Scheduler enable you to integrate it with the Resource Manager, to control and prioritize jobs These are the relevant components:
• Job classes Jobs can be assigned a class, and a class can be linked to a Resource
Manager consumer group Classes also control the logging level for their jobs
• Consumer groups Resource Manager consumer groups are restricted in
the resources they can use, being limited in, for instance, CPU usage or the number of active sessions
• Resource plans A Resource Manager plan defines how to apportion
resources to groups Only one plan is active in the instance at any one time
• Windows A window is a defined (probably recurring) period of time, during
which certain jobs will run and a certain plan will be active
• Window groups It is possible to combine windows into window groups, for
ease of administration
Prioritizing jobs within a window is done at two levels Within a class, jobs can be given different priorities by the Scheduler, but because all jobs in a class are in the same consumer group, the Resource Manager will not distinguish between them But if jobs
in different classes are scheduled within the same window, the Resource Manager will assign resources to each class according to the consumer groups for that class
Trang 8Using Job Classes
Create a class with Database Control, or through the API For example,
SQL> exec
dbms_scheduler.create_job_class(-
job_class_name=>'daily_reports',-
resource_consumer_group=>'dss',-logging_level=>dbms_scheduler.logging_full);
Then assign the jobs to the class, either at job creation time by specifying the JOB_
CLASS attribute, or by modifying the job later To assign a job to a class with the API,
you must use the SET_ATTRIBUTE procedure To put the job REPORTS_JOB into the
class just created,
SQL> exec
dbms_scheduler.set_attribute(-
name=>'reports_job',-
attribute=>'job_class',-value=>'daily_reports');
If there are several jobs in the one class, prioritize them with further SET_
ATTRIBUTE calls:
SQL> exec
dbms_scheduler.set_attribute(-
name=>'reports_job',-
attribute=>'job_priority',-value=>2);
If several jobs in the same class are scheduled to be executed at the same time,
the job priority determines the order in which jobs from that class are picked up for
execution by the job coordinator process It can be a value from 1 through 5, with 1
being the first to be picked up for job execution The default for all jobs is 3 This
could be critical if, for example, the class’s consumer group has an active session pool
that is smaller than the number of jobs: those jobs with the highest priority will run
first, while the others are queued
TIP To set priorities with Database Control, on the Options tab of the
Create Job window set the priority to one of “Very high,” “High,” “Medium,”
“Low,” and “Very low,” These are mapped onto the numeric values 1 to 5
EXAM TIP It is not possible to assign priorities when creating jobs with the
CREATE_JOB procedures—you must use the SET_ATTRIBUTE procedure of
the API subsequently
Logging levels are also controlled by the job’s class There are three options:
• DBMS_SCHEDULER.LOGGING_OFF No logging is done for any jobs in
this class
Trang 9TEST_JOB 16-JAN-05 11-00-00 FAILED
NIGHT_INCR 16-JAN-05 01-00-13 SUCCEEDED
NIGHT_ARCH 16-JAN-05 01-00-00 SUCCEEDED
More detailed information is written to the DBA_SCHEDULER_JOB_RUN_DETAILS view, including the job’s run duration and any error code it returned
Logging information is cleared by the automatically created PURGE_LOG job
By default, this runs daily according to the preconfigured schedule DAILY_PURGE_ SCHEDULE and will remove all logging information more than 30 days old
Using Windows
Create windows either through Database Control or with the CREATE_WINDOW procedure For example,
SQL> exec
dbms_scheduler.create_window(-
window_name=>'daily_reporting_window',-
resource_plan=>'night_plan',-
schedule_name=>'weekday_nights',-duration=>'0
08:00:00',-
window_priority=>'low',-comments=>'for running regular reports');
This window activates a Resource Manager plan called NIGHT_PLAN This might be
a plan that gives priority to the DSS consumer groups over the OLTP group It opens according to the schedule WEEKDAY_NIGHTS, which might be Monday through Friday
at 20:00 The window will remain open for eight hours; the DURATION argument accepts an INTERVAL DAY TO SECOND value, as does the REPEAT_INTERVAL for a schedule Setting the priority to LOW means that if this window overlaps with another window, then the other window will be allowed to impose its Resource Manager plan This would be the case if you created a different window for your end-of-month processing, and the end-of-month happened to be on a weekday You could give the end-of-month window HIGH priority, to ensure that the end-of-month Resource Manager plan, which could give top priority to the BATCH group, does come into effect
EXAM TIP Even if a job has priority 1 within its class, it might still only run
after a job with priority 5 in another class—if the second job’s class is in a consumer group with a higher Resource Manager priority
Trang 10If two windows with equal priority overlap, the window with longest to run will
open (or remain open) If both windows have the same time to run, the window
currently open will remain open
TIP Oracle Corporation advises that you should avoid using overlapping
windows
Exercise 22-2: Use Scheduler Windows to Control the Resource
Manager In this exercise, you will use the Scheduler to automate the activation of
the Resource Manager plan DAYTIME created in Exercise 21-1
1 Connect to your database as user SYSTEM with SQL*Plus
2 Run this query to determine which window is currently open:
select WINDOW_NAME,ACTIVE from dba_scheduler_windows;
3 Run this query to determine which Resource Manager plan is currently active:
select * from v$rsrc_plan;
You will see that one of the preconfigured plans (DEFAULT or DEFAULT_
MAINTENANCE) and its subplans are active
4 Temporarily clear whatever Resource Manager plan may be currently active:
alter system set resource_manager_plan='' scope=memory;
5 Confirm that there is no Resource Manager plan active:
select * from v$rsrc_plan;
This will return no rows.
6 Execute this procedure call to create a window named DAYTIME that will
activate the DAYTIME plan:
exec
dbms_scheduler.create_window(-
window_name=>'daytime',resource_plan=>'daytime',-start_date=>trunc(systimestamp) +
6/24,repeat_interval=>'freq=daily',-duration=>'0 12:00:00',comments=>'daily at 6AM');
This will open the window from now onward every morning at 6 o’clock, for
12 hours
7 Force the database to open the new window immediately:
exec
dbms_scheduler.open_window(-window_name=>'daytime',duration=>'0 00:05:00',force=>true);
This procedure call will open the window immediately and activate its plan,
but only for five minutes
8 Rerun the query from Step 3 or 5 to confirm that the DAYTIME window is
open and the DAYTIME plan is active
9 After five minutes, repeat Step 8 You will see that the window has closed
and that no plan is active This situation will persist until the next scheduled
opening of a window