Skip to Main Content
  • Questions
  • Kill a session from database procedure

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Fabricio.

Asked: May 17, 2000 - 11:38 pm UTC

Last updated: October 21, 2019 - 6:20 am UTC

Version: 7.3.4

Viewed 50K+ times! This question is

You Asked

How i can kill a session from a stored database procedure. There is some way to do this?

and Tom said...

Sessions are killed via the command

alter system kill session 'sid,serial#'

where sid and serial# are obtained from the v$session dynamic performance table.

Alter system is considered DDL and hence cannot be executed directly from PLSQL. We must use dynamic sql to accomplish this feat. In 7.3, we would use the dbms_sql package to accomplish this. It could look something like:

create or replace procedure kill_session( p_sid in varchar2,
p_serial# in varchar2)
is
cursor_name pls_integer default dbms_sql.open_cursor;
ignore pls_integer;
BEGIN
select count(*) into ignore
from V$session
where username = USER
and sid = p_sid
and serial# = p_serial# ;

if ( ignore = 1 )
then
dbms_sql.parse(cursor_name,
'alter system kill session '''
||p_sid||','||p_serial#||'''',
dbms_sql.native);
ignore := dbms_sql.execute(cursor_name);
else
raise_application_error( -20001,
'You do not own session ''' ||
p_sid || ',' || p_serial# ||
'''' );
end if;
END;
/



The owner of this procedure needs to have

o SELECT on v_$session granted to them by SYS. This grant must be directly to them, not via a role.

o ALTER SYSTEM granted directly to them -- not via a role.

To see why the caveat on granting directly to them is needed, please see:
</code> http://asktom.oracle.com/Misc/RolesAndProcedures.html <code>

You would then grant execute on this procedure to anyone you want. It would allow them to kill any session they own (running under their username). You would probably want to "grant select on v_$session" when connected as SYS to these people as well so they can 'see' the v$session dynamic performance view to get their sid/serial# pairs. Alternatively, you could:

create or replace view MySessions
as
select * from v$session where username = USER;

and grant them select on that view. That view will show them their sessions only.


Rating

  (24 ratings)

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

Comments

Kill a session from database procedure

Scott Morin, October 10, 2002 - 4:58 pm UTC

Granting alter system to the user allows them to kill any session to the procedure become redundant and offers no protection against the users killing any other session. Dangerous!

Tom Kyte
October 11, 2002 - 7:48 pm UTC

You missed the point entirely.

One of the primary uses of PLSQL stored procedures is to encapsulate logic.

Suppose, you wanted BOB and MARY to be able to kill sessions but NOT do any other ALTER SYSTEM commands? What would you do?

I would

a) create a schema, granting it the needed privs
b) create this procedure in there
c) grant execute on this procedure to BOB and MARY
d) lock the account (or just revoke CREATE SESSION from it, munge the password, whatever)


So, now BOB and MARY have the ability to kill sessions but not change ANY other system settings.

Further, since it is procedural logic, you CONTROL exactly what is going on. Maybe, you want to make it so that BOB can kill only HIS sessions and MARY only hers -- how easy would that be? Trivial. Oh wait, it already does that.






Kill a session from database procedure

Scott Morin, October 10, 2002 - 5:34 pm UTC

Granting alter system to the user allows them to kill any session to the procedure become redundant and offers no protection against the users killing any other session. Dangerous!

Tom Kyte
October 11, 2002 - 7:56 pm UTC

not when used as described! Then it makes it very very safe (and is the way to grant very very granular priveleges like just "kill session" or "kill your own sessions" to people).


Maybe I didn't make the fact that the "owner" of this procedure is some "utility" account like CTXSYS, MDSYS, ORDSYS, OUTLN and so on are in Oracle and should be "locked" and protected from general use.

how to kill a stored proc by name

Jerry, April 28, 2003 - 3:54 pm UTC

Tom,

Want to follow up on this. How do I kill a stored proc by name? I have a web user having multiple sessions open in the database. I only want to kill the one that's running stored proc. How do I find out which session is the stored proc since the sql_text is reflecting the queries within the stored proc.

Tom Kyte
April 28, 2003 - 4:19 pm UTC

have the developer put a call into their procedure using dbms_application_info.set_client_info -- that way you can tell what procedure it is.

In fact, have them put these calls all over their code -- setting the client_info, action, and module columns in v$session with useful information for you.

What is the datatype of SID / SERIAL#

Dilbert, June 17, 2003 - 2:48 pm UTC

Hi Tom,

Your procedure is a VERY VERY helpful one.
I have a question though about the parameters. The Input parameters are defined as VARCHAR2 while when I looked into the definition of v$session, both of them are NUMBER datatype. Is there a particular reason you made the Input parameters as Varchar2 ?

Tom Kyte
June 17, 2003 - 4:36 pm UTC

no reason in particular. does violate my "compare number to numbers strings to strings dates to dates" rule ;)

oversight, pure and simple

Drawback of killing session

kom, February 26, 2004 - 8:22 pm UTC

Hi Tom,
Our users will execute adhoc report queries say 10,000 a day on real time web application. Now some queries can return results in 1 min or some may take 5 hours to execute. I am in no position to filter which query will take how much time to execute.

I need to develop some kind of intelligence on which queries to execute immediately based on time they will take to execute or to form a queue to handle the big queries execution one at a time so that I do not stress my db server.

One method which I am thinking of is , send all queries to db server and put some kind of query timeout say 1 min, if the sql does not execute in 1 min than KILL the session and queue the SQL in a batch one at a time. In this way I will end up killing alot of sessions. Is there any drawback of killing sessions. Will the resources be used correctly.

Is the above way correct or please suggest me BEST way to handle this requirement.

Thanks in advance

Tom Kyte
February 27, 2004 - 7:21 am UTC

I would put all in a queue.

1 minute is 60 times too long for a web based application. 5 hours is just "longer".

No one should have to sit for a minute wondering "hmm, is my query ever going to come back" (i would not necessarily call this "real time").

So, I would use a queue of some form for all -- and then have some notification method (eg: email them a URL that when they click on it, instant report. SMS them when it is ready. give them a page they can goto to check the status. whatever you want...) to let them know it is done.

Additon

kom, February 27, 2004 - 9:28 am UTC

Hi Tom,
I told the business team that we need to queue all the incoming report request and notify the user as you mentioned, but they do not agree with this
.
They want all reports to be executed when requested and only those ones which do not execute in 1 min should be queued.
1) is there any command which will tell near realistic time to execute the query.
2) Will killing alot of sessions ( time < 1 min ) harm the system.

Can oracle save me in this case ?
I have oracle 8.1.7

Please suggest me the BEST way to handle this requirment.


Tom Kyte
February 27, 2004 - 10:03 am UTC

1) not really

2) yes, it'll waste that much time constantly.


The saviour would not be running things that take 1 minute interactively in a browser. could you imagine if google did that?


ugh. guess you could use the resource manager IN 9i and above, but not in 8i. In 8i, you'd have to let the silly thing run for a minute and have the system kill it (using a resource plan).




documentation on resource plan

Kom, March 01, 2004 - 4:05 pm UTC

Hi Tom,
I have oracle 8.1.7 on win 2k
I would like to read more on resource plan for my above requirment.
Can you please send me a link.
Thanks in advance,


Tom Kyte
March 01, 2004 - 4:51 pm UTC

otn.oracle.com has all documentation. you are interested in the Admin Guide (chapter on resource mgmt). All versions from 8.0 on up are there -- you want to look at either 9ir2 or 10g docs.

SN, March 01, 2004 - 5:18 pm UTC

Kom, you might want to tell your business users about Oracle Discoverer - It has the feature of predicting the expected run-time (with near accuracy). If it is too long then they can submit it in batch mode. The system you describe can't be classified "real time".

Killing the session of a running job

Faran, March 03, 2004 - 3:57 am UTC

Tom! how can we kill a session handling a long running internal job to update some very large tables. When I kill the session handling that particular job; It simply says that the session has been marked killed; but it doesn't release the locks on the underlying objects (involved in update by the job). I wanna know any method (in Oracle9i Rel. 2) by which Oracle can release the locks in such a case.

Thanks :)
Faran

Tom Kyte
March 03, 2004 - 9:53 am UTC

it is in the ACT of releasing the locks (watch used_ublk in v$transaction, you can watch it rolling back)

Hi Tom,

A reader, August 04, 2004 - 4:12 pm UTC

I understood your point of allowing users to kill their own sessions.
If we grant "alter system" privilege to a user, can they misuse it by doing certain other things apart from killing their own sessions through a procedure?

I want the alter system privilege for the user only when they execute the "kill_session" procedure.

Tom Kyte
August 05, 2004 - 8:42 am UTC

then you have everything you need here -- the original answer gives you that.

Hi Tom,

A reader, August 04, 2004 - 4:17 pm UTC

Please igonre my previous question. In fact you have answered it in the beginning of this thread.

But, I did not understood one of the steps you mentioned

"d) lock the account (or just revoke CREATE SESSION from it, munge the password,
whatever"

Can you explain what does it mean?

thanks,

Tom Kyte
August 05, 2004 - 8:45 am UTC

make it so the account that owns the procedure cannot log in if you want. secures it, you don't have an account that has alter system that someone can hack into.

lock it.

Find and kill he session which hangs

Sean, August 05, 2004 - 6:56 am UTC

Hi Tom,

The stored procedure to kill session is great. I have a question related to this technique.

Sometimes one developer have multiple sessions on the same host, is it possible to use v$session and some other views to find out which session is using which sql statement, so we can kill the session that hangs?

Thanks so much for your help.


Tom Kyte
August 05, 2004 - 12:56 pm UTC

search this site for showsql



kill session

A reader, September 01, 2005 - 12:35 am UTC


This gives an exact answer to user demands

Evan, May 12, 2006 - 10:34 am UTC

As usual, when I need an answer, I come to Ask Tom. One quick search, one right answer. I have not found that for any other product/vendor/expert.

I never need to ask a new question because the answers are almost always there.

Thanks,

Evan

How to kill session in RAC

sean, December 22, 2006 - 2:19 pm UTC

The procedure you mentioned works well in a single instance. But how do I implement it in RAC environment? Thanks so much for your help.

Sean

update procedure?

joshc, April 12, 2007 - 2:17 pm UTC

Very helpful.

How could we update this procedure for use in 10g?
Tom Kyte
April 13, 2007 - 12:20 pm UTC

you do not need to. it still works.

Does the original question work on 10.2..0.3

marc, February 02, 2009 - 1:14 pm UTC

I notices this thread was created in Oracle 8. Does it still work in 10.2.0.3. I receive the ora-1031 error.

I granted the owner the following grants.
SQL> SELECT   *
  2    FROM   user_sys_privs
  3   WHERE   privilege = 'ALTER SESSION'
  4  ;

USERNAME                       PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
testdbauser                      ALTER SESSION                            NO

SQL> 
SQL> SELECT   u.owner,
  2           u.table_name,
  3           u.grantor,
  4           u.privilege,
  5           u.grantable,
  6           u.hierarchy
  7    FROM   sys.user_tab_privs_recd u
  8   WHERE   table_name = 'V_$SESSION';

OWNER  TABLE_NAME   GRANTOR  PRIVILEGE  GRANTABLE     HIERARCHY
------ ------------  -------- ---------- ------------- ----------
SYS    V_$SESSION   SYS      SELECT     YES       NO


SQL>



grant execute on kill_session to testuser;

conn to testuser.

SQL> exec testdbauser.kill_session(1016,808);
BEGIN testdbauser.kill_session(1016,808); END;

*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "SYS.DBMS_SYS_SQL", line 1204
ORA-06512: at "SYS.DBMS_SQL", line 323
ORA-06512: at "FXBLOTTER.KILL_SESSION", line 9
ORA-06512: at line 1
 



What am i doing wrong?
Tom Kyte
February 02, 2009 - 1:46 pm UTC

that needs alter system, not session.

Also, please change the code to:

ops$tkyte%ORA10GR2> create or replace procedure kill_session( p_sid     in number,
  2                                            p_serial# in number)
  3  is
  4      ignore          pls_integer;
  5  BEGIN
  6      select count(*) into ignore
  7        from V$session
  8       where username = USER
  9         and sid = p_sid
 10         and serial# = p_serial# ;
 11
 12      if ( ignore = 1 )
 13      then
 14          execute immediate '
 15              alter system kill session ''' ||
 16              to_char(p_sid,'999999')||','||
 17              to_char(p_serial#,'999999')||'''';
 18      else
 19          raise_application_error( -20001,
 20                                 'You do not own session ''' ||
 21                                  p_sid || ',' || p_serial# ||
 22                                 '''' );
 23      end if;
 24  END;
 25  /

Procedure created.



I had a cursor leak in there...
And there is a small chance of sql injection in the old code.

Thanks

marc, February 02, 2009 - 2:26 pm UTC

Thanks, it was the typo in the grant.

Also, Any reason for the change to EXECUTE IMMEDIATE

Using it on Grid

Balaji Chellappa, March 10, 2009 - 3:10 pm UTC

Tom,
Is it possible to Kill a specific INSTANCE session by logging into any instance in a RAC/Grid environment?
Or should I have to login into that particular instanace to kill it's session?

Thanks
Balaji
Tom Kyte
March 11, 2009 - 2:55 am UTC

http://docs.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_2013.htm#i2065117


You must identify the session with the following values from the V$SESSION view:

*

For integer1, specify the value of the SID column.
*

For integer2, specify the value of the SERIAL# column.
*

For the optional integer3, specify the ID of the instance where the target session to be killed exists. You can find the instance ID by querying the GV$ tables.

Not working in 11g?

Jichao Li, August 12, 2011 - 3:20 am UTC

Tom,

This approach doesn't seem to work in 11.2.0.2 and I'm trying to wrap ALTER SYSTEM FLUSH SHARED_POOL and ALTER SYSTEM FLUSH BUFFER_CACHE in a procedure created in SYSTEM and grant the execute privilege to a TEST user. But I got ora-01031. This is for developer to flush memory cache when tuning their SQLs.

SQL> show user
USER is "SYS"

SQL> CREATE OR REPLACE PROCEDURE system.dev_flush_cache AS
  2      l_ddl VARCHAR2(100);
  3  BEGIN
  4      l_ddl := 'ALTER SYSTEM FLUSH SHARED_POOL';
  5      dbms_output.put_line(l_ddl);
  6      EXECUTE IMMEDIATE l_ddl;
  7      l_ddl := 'ALTER SYSTEM FLUSH BUFFER_CACHE';
  8      dbms_output.put_line(l_ddl);
  9      EXECUTE IMMEDIATE l_ddl;
 10  END dev_flush_cache;
 11  /

Procedure created.

SQL> create user test identified by test;

User created.

SQL> grant create session to test;

Grant succeeded.

SQL> grant execute on system.dev_flush_cache to test;

Grant succeeded.

SQL> conn test/test
Connected.
SQL> exec system.dev_flush_cache;
BEGIN system.dev_flush_cache; END;

*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "SYSTEM.DEV_FLUSH_CACHE", line 6
ORA-06512: at line 1

Tom Kyte
August 14, 2011 - 8:21 pm UTC

did you know that flushing the caches for "performance testing" is a really horribly bad, misleading, time wasting, not good for anything approach?

You are probably using a file system - a buffered file system. That means, the file system cache is already caching the stuff and just because we say we did a physical IO - it doesn't mean we did.

Search this site for "secondary sga" - to see what I'm talking about. Further - flushing the caches presents you with a situation you would NEVER SEE in real life.


I strongly encourage you to STOP THIS, do not do this, it is misleading, time wasting, not useful.


Secondly - DO NOT CREATE THINGS AS SYS. DO NOT USE SYS. sys is ours, sys is special, sys is magic, things work differently as sys than for other users. DO NOT USE SYS ever.

Thirdly - take the above and change SYS to SYSTEM, same applies. do not use thees accounts - use your OWN accounts.


ops$tkyte%ORA11GR2> connect /
Connected.
ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> drop user util;
drop user util
          *
ERROR at line 1:
ORA-01918: user 'UTIL' does not exist


ops$tkyte%ORA11GR2> create user util identified by util;

User created.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> grant create session, create procedure, alter system to util;

Grant succeeded.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> connect util/util;
Connected.
util%ORA11GR2> 
util%ORA11GR2> CREATE OR REPLACE PROCEDURE dev_flush_cache AS
  2      l_ddl VARCHAR2(100);
  3  BEGIN
  4      l_ddl := 'ALTER SYSTEM FLUSH SHARED_POOL';
  5      dbms_output.put_line(l_ddl);
  6      EXECUTE IMMEDIATE l_ddl;
  7      l_ddl := 'ALTER SYSTEM FLUSH BUFFER_CACHE';
  8      dbms_output.put_line(l_ddl);
  9      EXECUTE IMMEDIATE l_ddl;
 10  END dev_flush_cache;
 11  /

Procedure created.

util%ORA11GR2> 
util%ORA11GR2> grant execute on dev_flush_cache to scott
  2  /

Grant succeeded.

util%ORA11GR2> 
util%ORA11GR2> connect scott/tiger
Connected.
scott%ORA11GR2> exec util.dev_flush_cache;
ALTER SYSTEM FLUSH SHARED_POOL
ALTER SYSTEM FLUSH BUFFER_CACHE

PL/SQL procedure successfully completed.


A reader, August 15, 2011 - 1:07 am UTC

Tom,

Thank you. We'll seek other methods instead of flushing the caches on performance testing then. Anyhow it answered the question why the ORA-01031 was caused, that's because ALTER SYSTEM is not granted directly to SYSTEM.

Thank you again.

kill my session in RAC environment

aliyar, February 12, 2013 - 3:59 am UTC

HI Tom,

Thanks for your valuable informations.

can you please clarify below issue.

Database : 11gr2. 4 node RAC
Server : Exadata half rack.
O/s : Linux

i am writing a package for the developers. through which they can view all of their sessions using one function and they can kill their session using another procedure.

kill session procedure looks working fine. No issues.

but view sessions function is not showing the results properly.
suppose , i have only one session for the user " AELYAS " From  
instance 01. no sessions from other other nodes. when executing this function , it shows one session additionaly from each nodes.

following is the code for viewing sessions

function List_My_Session return Kill_Table PIPELINED is 
begin
for c1 in ( select inst_id,sid,serial#,username,osuser,sql_id from gv_$session 
where username in sys_context('USERENV', 'SESSION_USER'))
loop PIPE ROW (Kill_Format(c1.inst_id, c1.sid,c1.serial#,c1.username,c1.osuser,c1.sql_id ));
end loop;
return;
end;

create or replace type Kill_Format
as object(f int,
          a int,
          b int,
          c varchar2(20),
          d varchar2(20),
          e varchar2(100))
/


create or replace type Kill_Table
as table of Kill_Format
/

then i tested manually as follows:

first as sys user

SYSSQL> select count(*),inst_id from gv$session where username='AELYAS' group by inst_id;

  COUNT(*)    INST_ID
---------- ----------
  1     1

SYSSQL> 

it is fine.

now as normal user : granted select on gv_$session to this user


AELYASSQL> select count(*),inst_id from gv$session where username='AELYAS' group by inst_id;

  COUNT(*)    INST_ID
---------- ----------
  2     1
  1     2
  1     3
  1     4

AELYASSQL> 

here we can see one addition session from each node apart from the actual one session from node1

i really confused what went wrong here.  tried google as well. i could not find any solution

can you please help me here

Thanks
Aliyar

Tom Kyte
February 12, 2013 - 7:39 am UTC

the query against gv views is executed like a distributed query - we have to hit the SGA on each node.

so, you'll have a session on each node while the gv query itself is running.

kill session for RAC

aliyar, February 12, 2013 - 8:19 am UTC

Thanks tom for immediate reply.

when executing as sys user , we are seeing only one session.

so this behavior is only with non-SYS users ?

is there anyway to fix this issue?

Thanks
Aliyar
Tom Kyte
February 12, 2013 - 8:30 am UTC

as sys, the sessions would be created for sys, you are looking for user AELYAS, not SYS then.


first as sys user

SYSSQL> select count(*),inst_id from gv$session where username='AELYAS' group by inst_id;


:)


you could look at the current sql being executed in each session as well (join) and filter out the query that is currently running.

I am getting ORA-00031 error while running my procedure

Gaurang, October 18, 2019 - 5:13 pm UTC

I have created a prodedure to kill active session on a perticuler table. Procedure is created with no compilation error. While I was running that procedure to kill multiple active sessions I was getting below error message. what else I should add in my procedure to avoid this error?

ORA-00031: session marked for kill
ORA-06512: at "SYS.PROC_kill_SESSIONS", line 57
ORA-06512: at line 1
00031. 00000 - "session marked for kill"
*Cause: The session specified in an ALTER SYSTEM KILL SESSION command
cannot be killed immediately (because it is rolling back or blocked
on a network operation), but it has been marked for kill. This
means it will be killed as soon as possible after its current
uninterruptable operation is done.
*Action: No action is required for the session to be killed, but further
executions of the ALTER SYSTEM KILL SESSION command on this session
may cause the session to be killed sooner.

Status was not changing to KILL even after running this proc.

PS: I don't want to kill session through OS command and need to use oracle procedure only.
Connor McDonald
October 21, 2019 - 6:20 am UTC

When you kill a session, it is like *asking* the session to die, ie, "Hey, please stop".

Most of the time, the session will see this request and kill itself off. But if the session is totally hung/frozen then it might not be able to even do that.

Another possibility is that lets say your session has changed 1,000,000 rows and has not yet committed. Then when you kill it, then before it can be truly dead, it must rollback all those changes.

It is in situations like this, that you'll see things such as "session marked for kill". We *tried* to kill it, but it didn't sort itself out in 60 seconds.

For options, check out my killing sessions presentation

https://www.slideshare.net/hamcdc/oow19-killing-database-sessions

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