viernes, 27 de febrero de 2009

Matar sesiones Oracle en Windows

A veces necesitamos matar sesiones de la base de datos Oracle, muchas veces estas sesiones se quedan “colgadas” e inactivas incluso por dias, otras veces aunque están en estado activo se nos pide que las eliminemos.

Para matar una sesión contamos con el comando ALTER SYSTEM KILL SESSION 'sid, serial#'

Previamente debo de conocer el sid y el serial# de la sesión que deseo eliminar, en este caso quiero matar al usuario QUICK:

SQL> select sid, serial#, username, status from v$session;


SID SERIAL# USERNAME STATUS
---------- ---------- ---------- --------
370 226 ACTIVE
373 557 QUICK INACTIVE
381 90 SYS ACTIVE
383 1 ACTIVE
385 1 ACTIVE
386 7 ACTIVE
389 3 ACTIVE
390 3 ACTIVE
391 4 ACTIVE
393 1 ACTIVE
394 1 ACTIVE
395 1 ACTIVE
396 1 ACTIVE
397 1 ACTIVE
398 1 ACTIVE
399 1 ACTIVE
400 1 ACTIVE

17 rows selected.




El comando para eliminar el sid 373 es el siguiente:



SQL> alter system kill session '373,557';

System altered.





Sin embargo hay ocasiones en que ALTER SYSTEM KILL SESSION no libera los bloqueos que tenía la sesión que matamos.
Esto sucede cuando una sesión no puede ser interrumpida hasta que terminie la operación que está realizando.
En este caso, la sesión mantiene todos los recursos que obtuvo de nuestro servidor hasta que termina la operación.
Normalmente, la sesión que ejecutó el ALTER SYSTEM KILL SESSION recibe el mensaje: “the session has been marked to be terminated”.
Y la sesión aparece en v$session con status “KILLED”



SQL> select sid, serial#, username, status from v$session;

SID SERIAL# USERNA STATUS
---------- ---------- ------ --------
370 108 ACTIVE
373 557 QUICK KILLED
381 90 SYS ACTIVE
383 1 ACTIVE
385 1 ACTIVE
386 7 ACTIVE
389 3 ACTIVE
390 3 ACTIVE
391 4 ACTIVE
393 1 ACTIVE
394 1 ACTIVE
395 1 ACTIVE
396 1 ACTIVE
397 1 ACTIVE
398 1 ACTIVE
399 1 ACTIVE
400 1 ACTIVE

17 rows selected.







En linux tenemos la ventaja de poder matar el proceso del usuario con un kill -9, conociendo previamente el proceso del usuario.

La arquitectura de Windows no nos permite observar los distintos procesos que tiene Oracle, solo percibimos un oracle.exe, en el cual existen varios threads.

Para que en Windows nos podamos liberar de la sesión que quedó en estatus “KILLED”, podemos hacer cualquiera de las siguientes opciones:
1.Shutdown/Startup de la base de datos
2.Utilizar la utilería ORAKILL para eliminar threads.

Primeramente encontramos el thread con el siguiente query (debemos de conocer el thread previamente a ejecutar el comando ALTER SYSTEM KILL SESSION, de otra manera Oracle perdería la referencia al thread en cuestión):



SQL> select p.spid Thread, s.username Username, s.program
2 from v$process p, v$session s
3 where p.addr = s.paddr and s.username is not null;

THREAD USERNAME PROGRAM
------------ -------- -------------
364 SYS sqlplus.exe
4524 QUICK sqlplus.exe


SQL> exit



C:\Documents and Settings\Erika>orakill -h


Usage: orakill sid thread

where sid = the Oracle instance to target
thread = the thread id of the thread to kill

The thread id should be retrieved from the spid column of a query such as:

select spid, osuser, s.program from
v$process p, v$session s where p.addr=s.paddr




El comando por lo tanto sería:



C:\Documents and Settings\Erika>orakill OAS 4524

Kill of thread id 4524 in instance OAS successfully signalled.




Puesto que mi servicio se llama OAS.

A continuación en v$session vemos que ya no existe la sesión del usuario QUICK



SQL> select sid, serial#, username, status from v$session;


SID SERIAL# USERNAME STATUS
---------- ---------- ---------- --------
370 226 ACTIVE
381 90 SYS ACTIVE
383 1 ACTIVE
385 1 ACTIVE
386 7 ACTIVE
389 3 ACTIVE
390 3 ACTIVE
391 4 ACTIVE
393 1 ACTIVE
394 1 ACTIVE
395 1 ACTIVE
396 1 ACTIVE
397 1 ACTIVE
398 1 ACTIVE
399 1 ACTIVE
400 1 ACTIVE

16 rows selected.


Hay que tener cuidado porque al utilizar el comando ORAKILL para matar un thread corremos el riesgo de matar el proceso ORACLE.EXE

7 comentarios:

  1. Hola Erika,

    Muy interesante tu entrada, nadamás me quedó una pregunta; como le haces para saber que es lo que está ejecutando la sesión en cuestión; esto para saber si realmente debemos matarla o no

    Saludos!

    ResponderEliminar
  2. Que tal Esteban.
    De antemano sabiendo el sid o el nombre de tu usuario (de preferencia el SID ya que pueden haber varios usuarios conectados con el mismo nombre) puedes ejecutar el siguiente query:


    select sess.sid, sqltext.sql_text
    from v$sqltext sqltext, v$session sess
    where sqltext.address = sess.sql_address
    and sqltext.hash_value = sess.sql_hash_value
    and sess.username = 'QUICK';


    SID SQL_TEXT
    --- -------------------------------
    122 BEGIN dbms_lock.sleep(10); END;

    ResponderEliminar
  3. hola Amiga, que bueno q te veo por estos rumbos, me da gusto saludarte, sta muy bueno tu articulo, ns vemos pronto, saludos....

    ResponderEliminar
  4. Yo tengo una duda, que puede parecer simple, pero es que soy un simple "mortal" o sea desarrollador, ja ja ja.

    Hablas de Previamente debo de conocer el sid y el serial# de la sesión que deseo eliminar.

    Como puedo conocer el serial # y el sid de mi sesión, si estoy entrando a hacer consultas con un toad o plsql developer?

    yelics

    ResponderEliminar
  5. Hola Yelics.

    Es una muy buena pregunta.
    En realidad no puedes ver tu SID y SERIAL# con simples privilegios otorgados a PUBLIC (por default a todos).
    Para poder encontrarte tendrías que tener privilegio de lectura sobre v$mystat ( ahi verías tu SID) o v$session (ahi encuentras tu sid y serial# entre otras cosas)

    Lo que sí puedes saber y creo que es un hueco en seguridad en Oracle es lo siguiente:

    Esta prueba la hice en Oracle 10g:

    select * from v$session_connect_info;

    ahi encuentras los SID`s de todos los usuarios conectados a la base de datos (incluso sys y system!!! ) sin embargo no se encuentran los serial#.
    Si te conectas a la base de datos con un usuario de sistema operativo el cual nadie mas este utilizando para conectarse, será muy fácil encontrar tu SID en esta vista, si hay mas usuarios conectados, encontrarás varios SID`s para el mismo usuario de sistema operativo
    por ejemplo:

    select sid, authentication_type, osuser
    from v$session__connect_info;

    SID AUTHENTICATION_TYPE OSUSER
    ----- ------------------------- --------------------
    143 DATABASE MI_ORNENADOR\Erika
    143 DATABASE MI_ORNENADOR\Erika
    143 DATABASE MI_ORNENADOR\Erika
    143 DATABASE MI_ORNENADOR\Erika
    143 DATABASE MI_ORNENADOR\Erika
    144 DATABASE MI_ORNENADOR\Erika
    144 DATABASE MI_ORNENADOR\Erika
    144 DATABASE MI_ORNENADOR\Erika
    144 DATABASE MI_ORNENADOR\Erika
    144 DATABASE MI_ORNENADOR\Erika
    148 INTERNAL Erika
    149 DATABASE Erika
    149 DATABASE Erika
    149 DATABASE Erika
    162 INTERNAL MI_ORNENADOR\Erika




    De aqui tengo lo siguiente:
    Sys = SID 148
    un usuario de desarrollo = SID 149
    otro usuario de desarrollo = SID 144
    otro usuario de desarrollo = SID 143

    como ves, no se puede identificar cual usuario es cual entre los sids 144 y 143 dado que estan usando el mismo usuario de sistema operativo.

    ResponderEliminar
  6. me podria yesica orientar con lo siguiente, tengo SID de la sesion que mate por OEM, al dar la instrucción ALTER SYSTEM KILL SESSION '15, 29131' me dice que esta marcada para killed; esto es en solaris y me tiene bloqueada una tabla que necesito lo que no conozco es el proceso en solaris para utilizar kill -9 xxx

    gracias
    Mariao

    ResponderEliminar
  7. Hola Mariao.

    Antes de matar una sesión, te recomiendo que busques primero el proceso, porque si lo matas y te pone el status como "killed", como te diste cuenta, ya no puedes obtener el proceso de sistema operativo.

    Si lo haces desde OEM, es mas sencillo porque el entorno gráfico te muestra la misma sesión con dos tipos de bloqueo: TM y TX, primero mata el que se muestra como TM.

    Espero te sirva.
    Saludos!

    ResponderEliminar