Find out why scheduled oracle job stopped running - oracle

I have a job started by the scheduler which tracks its sub-steps in a JOB_LOG table. Since yesterday, 17 o'clock it stopped logging its activity. This could mean that the job encountered an error, or that it is really taking this long, but that is unlikely since the entire job with all sub-steps usually doesn't take more than 4 hours.
If I run exec DBMS_SCHEDULER.STOP_JOB ( job_name => 'RUN_JOB', force => true); it tells me there is no job running. Just to be sure, I did an exec dbms_scheduler.enable('RUN_JOB'); which did not give errors.
Looking at the job in SQL developer, I see the job is enabled and that is supposed to run every 15 minutes, but I don't see any output in the logging table indicating a new job has started.
How can I find out what the reason for the stopped logging and the non-running job is?
I could try to run the job by exec DBMS_SCHEDULER.RUN_JOB('RUN_JOB'); but that would only obscure the actual error (assuming it works).
How can I look at the internal state of the job scheduler for this job? I would be especially interested in how the scheduler treats jobs that are still running (So that it doesn't start them every 15 minutes unless completed).
The output of SELECT JOB_NAME, STATE FROM DBA_SCHEDULER_JOBS WHERE JOB_NAME like 'RUN_%'; is RUN_JOB SCHEDULED;
The job has RUN_COUNT and FAILURE_COUNT of 12.
More information: If I run select JOB_NAME, STATUS, ERROR#, ADDITIONAL_INFO, ACTUAL_START_DATE from ALL_SCHEDULER_JOB_RUN_DETAILS where JOB_NAME like 'RUN_%' order by ACTUAL_START_DATE DESC;
I get error messages about ORA-00001: unique constraint (RATOR_MONITORING.JOB_LOG_PK) violated. This probably means there is an issue with the sequence generating the primary keys.

I was able to locate the issue by calling:
select JOB_NAME, STATUS, ERROR#, ADDITIONAL_INFO, ACTUAL_START_DATE from ALL_SCHEDULER_JOB_RUN_DETAILS where JOB_NAME like 'RUN_%' order by ACTUAL_START_DATE DESC;
This was also helpful in seeing that the job was being run, but with errors:
SELECT * FROM DBA_SCHEDULER_JOBS WHERE JOB_NAME like 'RUN_%';

Related

query for to know result scheduler jobs in oracle

I have many jobs running in my database. There is into all_scheduler_job_run_details table job_name,req_start_date and status.how can I write query for, when last time worked each jobs what their status was?
select job_name ,staus,max(req_start_date) from all_scheduler_job_run_details where owner='ALI' group by job_name
this is my code
If you just want the most recent execution, and assuming the jobs are not running right now, you can probably get away with:
select job_name, state, last_start_date
from all_scheduler_jobs
where owner = 'ALI'

In adbtask_settings Oracle Table what is the meaning of INTERVAL and max_run_time column?

In adbtask_settings Oracle Table what is the meaning of INTERVAL and max_run_time column? This table is being used for AUTOTask job execution so I want to know the significance of these columns.
The column in table adbtask_settings.
Interval=180 -- it means every 180 seconds, Autotask will try to schedule your task.
max_run_time=900 -- it means if client task already run for 1800 seconds but not yet finish, a timeout error will be signaled to interrupt client task
which means that is the maximal runtime allowed.
If you want test these functionalities then you use below proc to change the value and check the job execution time in below SELECT query:
execute DBMS_ADBTASK_ADMIN.MODIFY_ADBTASK_SETTINGS ('Auto Compress','INTERVAL',180);
execute DBMS_ADBTASK_ADMIN.MODIFY_ADBTASK_SETTINGS ('Auto Compress','MAX RUN TIME',900);
select run_duration from DBA_SCHEDULER_JOB_RUN_DETAILS where job_name='ORA$_ATSK_AUTOCOMP' order by actual_start_date desc;

Oracle scheduler chain_start status is still running when there are no running job

I have a job scheduler to run a chain daily but from USER_SCHEDULER_JOB_LOG it seems like operation: chain_start are still in running status while operation: chain_run shown completed. Why is that so?
Besides that, SELECT * FROM ALL_SCHEDULER_RUNNING_JOBS returns no rows.
What is wrong with the job that the chain_start did not complete?
Attached snippet from USER_SCHEDULER_JOB_LOG
Please, provide with output of the following queries:
SELECT * FROM ALL_SCHEDULER_JOBS WHERE OWNER NOT IN ('SYS');
and
SELECT * FROM ALL_SCHEDULER_JOB_RUN_DETAILS WHERE OWNER NOT IN ('SYS');

Can I get a return value in some way from a dbms_scheduler job?

I have a webpage (generated via PL/SQL) that allows someone to toggle a remote device on or off. They are presented with a list of devices and they use checkboxes to select the ones to toggle. UTL_HTTP is used to communicate with the devices. Currently, the devices are toggled serially. Once all have been toggled, an email is sent to the user. Depending on how many devices are selected, doing this serially has the potential to take too long. So I'm looking at using DBMS_SCHEDULER to execute the toggling in parallel.
The problem is that the toggling process returns a status, either 'OK' or the reason it failed. I need that result to include in the email to the user. So, I need the 'main' procedure to create the SCHEDULER jobs and then wait for them to finish (and somehow get their statuses) before sending an email to the user.
Is this possible, short of having each job write it's status to a table which is polled by the 'main' process? I've read references to DBMS_PIPE for inter-process communication, but haven't found a good example (ie, one that makes sense to me) showing how to do it.
If there's a way to do it, I couldn't figure it out. I ended up having each job write it's status to a table. The main process knows how many individual jobs were created and polls the table to tell when all jobs are finished (or it timesout after a specified amount of time has passed, in case one of the jobs dies for some reason).
An Alternate Solution to Watching Parallel Processes Run Through DBMS_SCHEDULER Jobs
New Edit: An Abbreviated Discussion of the Core Problem
(Edit: 03/10/2014) I added this discussion after some helpful feedback from one of the posters watching this thread.
Opening Comments: Other discussion threads here mention the use of some output value from the function call itself. This is not natively possible with the existing DBMS_SCHEDULER features.
There are no OUT type parameter values or function outputs related to notifying a condition encountered by the procedure invoked. The most immediate problem at hand is: How do we run a series of related tasks via PL/SQL stored procedure in parallel? (i.e., without waiting for one another to finish before each start themselves.)
Whatever invokes the procedure tasks should not wait around for a status output. The response time is likely to be widely variable and whatever calls the procedure in this way would also hang. Associated processes would be waiting for the completion of the procedure or the return of a specified output.
A Suggested Approach: Other comments on this problem are on the right track. Have the custom output written to a table where it can be queried later when a response is ready. If you really want to make this a hands-off task, try putting a trigger on the output table. Every time a message of a specific value (representing a completed state of the request) is populated, invoke a procedure with Oracle's Mail package that sends out your notification email.
How to Track Your Invoked Jobs By Understanding DBMS_SCHEDULER Features
Using a scheduled job is a good way of initiating and watching a set of procedure calls that are not sequentially dependent on one another. I have been able to accomplish a similar approach using the original DBMS_JOB functionality of previous versions of the Oracle database.
A Case Study: Using a web-based application interface (Oracle Application Express) I had a project which allowed the user to initiate a resource-intensive series of database operations. Initiating the request was all that was needed.
The Actual Use Scenario: The user didn't need to wait around for its completion. The problem was that wiring the web request form directly to a call to this database package and its procedures also tied down control of the form and its session making the user "wait" for the procedure itself to complete.
Firing off a scheduled job that invoked this process separated the interaction with the web page from the wait for the actual process to complete. Scheduling a job task was almost instantaneous, so the wait between the submission of the request and return of control back to the web page also had a negligible wait.
Using Oracle DBMS_SCHEDULER: An Introduction to the Approach
The Current Problem and Solution Under Discussion: Use the native DBMS_SCHEDULER status views to monitor the progress of your process. There are many, but ALL_SCHEDULER_JOB_LOG is the simpler of the collection and is a good start to what we're trying to accomplish.
Use an easily identifiable name for each job... and also each job that may be related to one another.
Initiate an additional job to watch all the parallel tasks until the last one is completed. Alter this "watching" job to end once this condition has been met.
The Basic Syntax to Initiate a Database Job on Scheduler
The procedure DBMS_SCHEDULER.CREATE_JOB creates a job in a single call without using an existing program or schedule:
DBMS_SCHEDULER.CREATE_JOB (
job_name IN VARCHAR2,
job_type IN VARCHAR2,
job_action IN VARCHAR2,
number_of_arguments IN PLS_INTEGER DEFAULT 0,
start_date IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,
repeat_interval IN VARCHAR2 DEFAULT NULL,
end_date IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,
job_class IN VARCHAR2 DEFAULT 'DEFAULT_JOB_CLASS',
enabled IN BOOLEAN DEFAULT FALSE,
auto_drop IN BOOLEAN DEFAULT TRUE,
comments IN VARCHAR2 DEFAULT NULL);
These are the input parameters that you should pay close attention to:
job_name You can leave it to default, or you can help organize your job requests by using a consistent naming convention. JOB_NAME is a special parameter because it has a helper function called *GENERATE_JOB_NAME*, where you can specify a naming prefix to combine with the internal name assignment. This isn't absolutely necessary, but it helps.
DBMS_SCHEDULER.GENERATE_JOB_NAME
(prefix IN VARCHAR2 DEFAULT 'JOB$_') RETURN VARCHAR2;
An example call within the create_job definition:
job_name => dbms_scheduler.generate_job_name( prefix => 'MY_EXAMPLE_JOB_')
So in the example above, we could have a series of jobs with names like: MY_EXAMPLE_JOB_0001, MY_EXAMPLE_JOB_0002, MY_EXAMPLE_JOB_0003...
job_type This one is straight from the Oracle documentation. Most likely it will be the type: *plsql_block* (The value may also be case sensitive).
repeat_interval Do not set this value for your one-time parallel tasks. The job will identify itself as completed once the referenced stored procedure reaches completion, or errors out.
end_date Leave this null or unassigned as well. This value does not apply for a one-time execution of the procedure it is watching.
start_date Leave this null or unassigned as well. No value means to initiate the specified job as soon as the job is ENABLED.
enabled Defaulted to FALSE you will need to set this to TRUE as soon as you create the job, or when you're ready to initiate the process "thread".
auto_drop This is an important one. The rest of this method depends on the meta data of each job remaining in the DBMS_SCHEDULER's log tables even after they have hit an exception or reached completion. Set this to FALSE.
job_action This will vary depending on the number of parallel processes you initiate. First, you should initiate the first of your parallel processes... and also the related "Monitoring" process that will be active for a specific request. Job actions for a plsql_block type job looks something like this:
Example PL/SQL Block:
BEGIN my_procedure(a, b, c); END;
Creating a Job Monitoring Process
Part of the problem you encountered is that DBMS_SCHEDULER may watch a process of varying execution time, but it's not very good at letting you know when it's done or if it encountered an exception.
Your "watcher" process just needs to be another scheduled job that queries the ALL_SCHEDULER_JOB_LOG table for the procedures it's responsible for, and figures out if all of them have reached the desired closing status.
Assumption: For a given request, you will know the number of parallel processes (remotely initiated switching events) required to complete this type of request... all the processes do not have to start exactly at the same time, but the watcher will need to know it still has to wait, even if all the related processes it can see have matched its criteria as "completed".
The kinds of tasks your "watching" procedure will need to include:
WATCHING SQL Criteria Example:
WITH MONITOR_QUERY AS (
SELECT COUNT(LOG_ID) AS COMPLETED_PROCESS_COUNT
FROM ALL_SCHEDULER_JOB_LOG
WHERE JOB_NAME LIKE '001-REQUEST%')
SELECT CASE WHEN COMPLETED_PROCESS_COUNT = <TOTAL_PROCESSES>
THEN 'DONE' ELSE 'IN-PROGRESS' END as REQUEST_STATUS
FROM MONITOR_QUERY
Also note that when you call the job that runs the monitoring process, you may find it useful to generate a unique job name ahead of time before kicking off its repeating job (should be done only once per request or set of parallel jobs):
DECLARE
who_am_i VARCHAR2(65);
BEGIN
SELECT dbms_scheduler.generate_job_name
INTO who_am_i
FROM DUAL;
--
DBMS_SCHEDULER.CREATE_JOB (job_name => who_am_i,
job_type => 'plsql_block',
job_action => 'BEGIN my_monitoring_task(p_1, p_2, who_am_i); END',
repeat_interval => 300,
comments => 'Interval time units are defaulted to SECONDS';
...);
END;
This job is most effective if it is created at the same time or shortly after the first parallel job in the series is launched.
When The Monitored Request is Completed
When the selection criteria is met (i.e., all related processes are closed in some way) then it's time to fire off your notification and also to stop the watcher for this request.
Stopping the Monitoring Job
DBMS_SCHEDULER.STOP_JOB (
job_name IN VARCHAR2
force IN BOOLEAN DEFAULT FALSE);
job_name If you used a custom naming scheme for each job you initiate, you could also store this value as an input parameter into your watcher procedure call. The watcher would then know how to shut itself off when it's done. Remember, if you use the GENERATE_JOB_NAME function call, you are only specifying the prefix to the entire job_name used in the scheduler.
force Set this one to FALSE (The default) or leave it unspecified. It is better to let Oracle find a way to gracefully put your watcher job to a halt.
Closing Thoughts and Comments
If the outcome or completion of several of your procedures are related, an additional scheduled job can be repeated as a monitoring "heartbeat" to check if all the dependencies for a discrete process have been met.
A comment on clean-up: This design requires the *auto_drop* parameter set as FALSE. A daily or weekly process could also be scheduled to issue a *drop_job* command that will clean up the scheduler's logs of records related to completed and reported requests.
You can also see, by including the invoking *job_name* within the scheduled job itself, you can provide the procedure(s) contained within it the ability to turn itself off once the right conditions have been met.
Advanced Queues to the rescue.
Slave sessions (jobs), when they are ready, put their return values into an AQ (practically any data structure is allowed).
The coordinator session, which initiated the slaves, listens on the queue and gathers the return values.
Actually, AQs are the recommended way for intersession communication in Oracle anyway.
In Oracle 12c the column ALL_SCHEDULER_JOB_RUN_DETAILS.OUTPUT can be used to return values from a job.
For example, create a job and write output using DBMS_OUTPUT:
begin
dbms_scheduler.create_job(
job_name => 'TEST_JOB',
job_type => 'PLSQL_BLOCK',
job_action => q'[begin dbms_output.put_line('Test output'); end; ]',
enabled => true
);
end;
/
Now read the output:
select job_name, to_char(log_date, 'YYYY-MM-DD') log_date, output
from all_scheduler_job_run_details
where owner = user
and job_name = 'TEST_JOB'
order by log_date desc;
JOB_NAME LOG_DATE OUTPUT
-------- -------- -------
TEST_JOB 2017-12-26 Test output
If you are able to use oracle version 11, you might use the DBMS_PARALLEL_EXECUTE pl/sql package, which does what you want. If you cannot upgrade, then you can implement some c callouts from pl/sql which provide similar functionality.
If you decide to use dbms_pipe and you are using the RAC database option be aware that using DBMS_PIPE has its limitations for failover.

Oracle Job not been executed for no reason

Im programing a job in oracle in order to execute a store procedure, but when the time comes it just does not happend any thing for no reason.
Is there some kind of log where I can see if an error happend or something?
Im using the dbms_job package to create the job
Tnks.
Since you're using DBMS_JOB
Are you committing after making the call to DBMS_JOB.SUBMIT? Your job can't run until you've committed.
Have you set JOB_QUEUE_PROCESSES to a non-zero value? Are there any other DBMS_JOB jobs running in your system?
Can you post the results of running the following query:
SELECT last_date,
last_sec,
next_date,
next_sec,
this_date,
this_sec,
broken,
failures,
total_time
FROM dba_jobs
WHERE job = <<your job number>>

Resources