Skip to Main Content
  • Questions
  • How to kill a procedure running via DBMS_JOB queue...

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Kamal.

Asked: May 28, 2003 - 8:54 pm UTC

Last updated: April 12, 2010 - 7:07 pm UTC

Version: 817

Viewed 10K+ times! This question is

You Asked

Hi Tom,
We have a requirement where we want to schedule a procedure to run via DBMS_JOB queue and a web interface to show the progress of the procedure.
We are planing to create the procedure such that it puts information at each logical step completion using dbms_application_info.set_client_info.
The web interface may then read this info to find out how far in the code the procedure is at this time.

Do you think this is optimal solution? Any ideas?

We also want to support a way to signal termination (or kill) of this procedure via the web interface. The idea is that the web interface will place a request to kill this running procedure (maybe because its taking longer than it should to finish...) and we should go ahead and kill this job (the session its running under) programmatically.

Any ideas how we could do that from within Oracle? (kill the procedure running via dbms_job queue). We could remove the dbms_job entry for this job, but I guess this will not affect the currently running copy of the procedure.
Thanks,


and Tom said...

you can use dbms_application_info.set_session_longops instead, it supplies more information about progress and even guestimates time to completion. search for that string on this site for examples....


you would have to kill the session behind the job or better yet -- you could do this

o the job is going to call dbms_application_info anyway
o put that call into a "special procedure"
o have that special procedure look to see if an ALERT that it registered for (read
about dbms_alert) was fired
o if it did fire, this procedure should

RAISE PROGRAM_ERROR;

o the top level "job" submitted would be:

begin
dbms_alert.register for the kill event
do_the_procedure;
dbms_alert.unregister yourself
exception
when program_error then
rollback;
dbms_alert.unregister yourself
null; -- I was killed, just exit
when others then
dbms_alert.unregister yourself
RAISE;
end;


that would be "nicer". It wouldn't be good to kill the job queue process. Exiting normally as we did here will just remove the job normally from the queue.

Rating

  (14 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Just what I was looking for..

Kamal Kishore, May 29, 2003 - 7:58 pm UTC

Thanks a lot.


Any overhead for setting TIMED_STATISTICS to TRUE?

Kamal Kishore, May 30, 2003 - 10:53 am UTC

Hi Tom,
The Oracle documentation says the following about the V$SESSION_LONGOPS stats gathering:

<quote>
V$SESSION_LONGOPS
This view displays the status of various operations that run for longer than 6 seconds (in absolute time). These operations currently include many backup and recovery functions, statistics gathering, and query execution, and more operations are added for every Oracle release.

To monitor query execution progress, you must be using the cost-based optimizer and you must:

Set the TIMED_STATISTICS or SQL_TRACE parameter to true
Gather statistics for your objects with the ANALYZE statement or the DBMS_STATS package
You can add information to this view about application-specific long-running operations by using the DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS procedure.
</quote>

It says that you must set TIMED_STATISTICS to TRUE to get meaningful information in this view. Is there any overhead for setting this to TRUE permanently in a production system?

Can it be set to TRUE always, or is it used only when there is a performance problem (to evaluate the long running queries)?

Do you think it would be possible to convince the DBA's to set it to TRUE for a production system?
Thanks,



Tom Kyte
May 30, 2003 - 11:58 am UTC

I have it on all of the time in all of my systems. Its on on our stuff.

as for whether it will be possible to convince your dba's, well, that is a function of who your dba is more then another else. some people don't believe anything.

killing session behind job

M vd Laan, November 15, 2004 - 9:39 am UTC

What can go wrong when killing the session behind a job?



Tom Kyte
November 15, 2004 - 1:28 pm UTC

you might get caught and sent to jail....

only kidding.

just that the job if it was in the middle of doing something large will start rolling back and might take a while to finish rolling back.

not much different from killing any session (except this one will have a life of its own and start all over again, it is what jobs do...)

Identifying a session for purposes of killing later...dbms_job

Prashant, December 04, 2004 - 7:04 pm UTC

Hi Tom,

I have had trouble finding out a session id, for purposes of killing it later, in case the user decides to abort the job, if it happens to run longer or some other reason. As the job is submitted through a dbms_job, I have to store the session id so that I use it for killing the job, when my main process is killed. 
(I am using the approach of 
a) Setting the job to broken
b) kill session
c) dbms_job remove)


However I am unable to get the session id in my procedure as it gives me the following error.

SQL> exec job_submit;
BEGIN job_submit; END;

*
ERROR at line 1:
ORA-20001: ORA-06550: line 2, column 64:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 2, col
ORA-06512: at "SRS_STAGE.JOB_SUBMIT", line 21
ORA-06512: at line 1

The tables and stored procedures that I am using are below.
create table job_parameters_log (job_id NUMBER, sid NUMBER);


CREATE OR REPLACE PROCEDURE job_submit

IS

   l_job PLS_INTEGER := 0;
 
BEGIN

         dbms_job.submit(l_job, 'declare l_job_id number := JOB; l_sid NUMBER; 
                                    begin select sid into l_sid from v$mystat where rownum = 1;
                                    p(JOB,l_sid);
                                 end;'
                          );
 
                      
         commit;                      

EXCEPTION
     WHEN OTHERS THEN
         ROLLBACK;
         RAISE_APPLICATION_ERROR (-20001, SUBSTR(SQLERRM,1,100));

END;
/

CREATE OR REPLACE PROCEDURE p
(
   p_job_id_in          IN NUMBER,
   p_sid_in             IN NUMBER
)
IS


BEGIN
   INSERT INTO job_parameters_log(job_id, sid)
   VALUES(p_job_id_in,p_sid_in);
   
   COMMIT;

EXCEPTION
     WHEN OTHERS THEN
         ROLLBACK;
         RAISE_APPLICATION_ERROR (-20001, SUBSTR(SQLERRM,1,100));

END;
/

What I understand is the I need to have access to v_$session granted to me directly, not via role? Is that correct, if it is, then how should I get my DBA to get it for me, because I don't think he will provide me access to the underlying view in a production environment.

Another question is my approach of killing a session mentioned earlier OK?

Thanks 
Prashant 

Tom Kyte
December 04, 2004 - 8:23 pm UTC

</code> http://asktom.oracle.com/Misc/RolesAndProcedures.html <code>


yes, you are correct -- and "why wouldn't they"?

ask them for the sound technical reason -- and then we can talk.

Killing child sessions spawned from main thread

Prashant, December 05, 2004 - 6:14 am UTC

Hi Tom,

Thanks for the reply. I should be able to convince the DBA's.
I would also like to know that if I have launched a main procedure which in turn submits say 3 dbms_jobs. And waits for their completions using the logic (as you mentioned in one of your followup's sleep and check the status of jobs)
loop
dbms_lock.sleep(10);
check;
exit when condition met;
end loop;

So the main process only completes when all of the child processes have completed.
However if the jobs are running for an indefinitely long time, I will abort the main process which in turn should abort all the child processes. After figuring out the problem and perhaps a code fix I will re-start the main procedure again (of course in production ideally this shouldn't happen, but anyway I would like to take care of this eventuality).

Can I use the following logic to achieve the same?

<<declare section in main procedure>>
e_user_cancelled_operation EXCEPTION;
PRAGMA EXCEPTION_INIT(e_user_cancelled_operation,-1013);

<<exception handler>>
when e_user_cancelled_operation THEN
kill_dbms_jobs_child_proc

The kill_dbms_jobs_child_proc will have the logic as I mentioned in my last followup (of course taken from your followups), which is,
a) Identifying the child sessions (dbms_job sessions) I need to kill. (I have a parameter table that stores job name, parameters, sid for the processes spawned)
a) Setting the jobs to broken
b) killing the sessions
c) dbms_job remove.

Please let me know whether its possible for me to achieve this.

Thanks
Prashant


Tom Kyte
December 05, 2004 - 7:38 am UTC

seems reasonable -- except for catching a ctl-c. that break breaks you right out of the code.

Prashant, December 05, 2004 - 4:35 pm UTC

Hi Tom,

Thanks for the response....but sorry to be bothering you yet again. So can I come to know if a user has manually aborted a main process? So that i can trigger off the chain of events needed to kill the child processes.

Thanks
Prashant

Tom Kyte
December 05, 2004 - 7:07 pm UTC

you cannot really, ctl-c is ctl-c. You'd have to have the child processes looking occasionally for their "parent" -- or writing some sort of "monitor" process that is part of this entire chain.

Why would you let the end user ctl-c? why not give them a nice little interface with a push button or something to cancel the job?

Replicating ctl-c....

Prashant, December 05, 2004 - 7:32 pm UTC

Hi Tom,

Thanks for responding...you mentioned
<<why not give them a nice little interface
with a push button or something to cancel the job>>

This functionality that you are talking about would actually call the code that I have written for kill_dbms_jobs_child_proc (I mentioned this in my earlier followup) as well I need to kill the parent proc?

Thanks again
Prashant


Tom Kyte
December 05, 2004 - 8:42 pm UTC

you don't "need" a parent proc if you do this, this would be the parent proc, but one they do not "ctl-c", but hit a button and say "stop watching the children -- stop them instead"

the little program would be the polling loop -- every "n seconds" look at see if children still running -- on button press event, stop em and exit.

Thanks a lot Tom....it cleared my doubts...Prashant (n/t)

Prashant, December 05, 2004 - 10:23 pm UTC


Pretty cool

Craig, August 06, 2006 - 10:21 pm UTC

If I'm understanding the example you gave in answer to the original question, you would periodically have to check waitone or waitany to see if there were a msg waiting for you, right? (obviously, this is my first foray into dbms_alert). So aside from actually killing the process from OEM or the shell, is there anyway to "signal" oh, say, a long running insert to die?

The problem I'm having is that if I kill a long running job from the shell, it seems to bypass the exception handler w/in the job (meaning that it dies right then and there). It'd be nice to be able to kill something, but at least record that something bad happened.

Thanks

Tom Kyte
August 06, 2006 - 11:48 pm UTC

if you would like your long running process to "die gracefully", it'll have to cooperate - yes.

every now and again "peek" and see if it should just "go away"

How to identify the SID in v$session_longops

Diieter, January 20, 2007 - 4:54 am UTC

Hi Tom,

I've just read this article and miss one detail in your first answer. How would the session calling dbms_job.submit now for what SID to look in the v$session_longops table when trying to "poll" for the current progress status?

Thank you for all the great help,

Dieter

How to identify the SID in v$session_longops

Diieter, January 20, 2007 - 4:55 am UTC

Hi Tom,

I've just read this article and miss one detail in your first answer. How would the session calling dbms_job.submit now for what SID to look in the v$session_longops table when trying to "poll" for the current progress status?

Thank you for all the great help,

Dieter

a quick one

Dieter, February 19, 2007 - 4:47 pm UTC

Hi Tom,
I was wondering, if you could have a look at my last feedback.
Thank you
Dieter
Tom Kyte
February 19, 2007 - 9:23 pm UTC

it would not really, unless your job did something like dbms_application.set_client_info to identify itself easily (to find the row in v$session)

Is killing a procedure good practice...

Prats, April 01, 2010 - 8:35 am UTC


Tom,

I am currently working on an application dealing with huge data[TB].This DB get data very frequently and few procedures run after every 5 minutes to rollup the data to corresponding tables.

Now while providing a upgrade script, I am currently stuck with a peculiar issue.

Firstly I go ahead and drop all jobs and procedures.
If by then one of the procedure is started, it would lock involved tables.
If my upgrade procedure also tries to alter this table then it fails while waiting for the locked object.


What strategy should I follow to ensure none of rolling-up procedure are running before upgrade procedure starts running.
I know killing a procedure is not a good solution here. Please provide pointers on this...Thanks
Tom Kyte
April 05, 2010 - 1:02 pm UTC

disable all relevant jobs
query dba_jobs_running (or the scheduler views if you are using that)
and if there aren't any running - go ahead and upgrade, else, wait, try again later.

Is killing a procedure good practice

Prats, April 06, 2010 - 6:35 am UTC

I would not have the liberty to wait for my executing procedures to end [They might take hours in some extreme cases].

Since I don't have redolog files being maintained, can I go ahead and kill the job. I agree that this will result in have processed data, but I my customer is ok with that. He simply doesn't want to wait for long for upgrade.

Is killing the job the only alternative I have or is there any other better option.
Tom Kyte
April 12, 2010 - 7:07 pm UTC

Since I don't have redolog files being maintained,

sure you do, we always do that.


I cannot tell you if killing your process is OK, umm, only you can sort of decide that. I've no idea what it does!

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library