miércoles, 20 de mayo de 2009

Script para limpiar conexiones inactivas en oracle

Cuando se usa alguna de las versiones gratuitas de oracle, solo es posible mantener cierto número de conexiones abiertas en determinado momento, por lo que es necesario, acabar con conexiones que no se estén utilizando. Aunque desde el código de la aplicación se puede hacer, existen ocasiones en las cuales, por algún motivo u otro, se quedan abiertas y es necesario cerrarlas. Para ver las conexiones registradas por Oracle, podemos ejecutar el siguiente comando:

SELECT * FROM SYS.V_$SESSION WHERE STATUS = 'INACTIVE' AND SCHEMANAME<>'SYS'

Con la condición, no queremos que nos muestre las conexiones al esquema SYS, ya que son las usadas por oracle. Nos mostrará las conexiones inactiva, podemos cambiar el la condición del campo STATUS a 'ACTIVE', 'INACTIVE' o 'KILLED'. Si quitamos esa condición nos mostrará todas las conexiones registradas en ese momento.

Al realizar la consulta, existen ciertos campos a los cuales presenta valiosa información, el primero es el campo llamado LAST_CALL_ET, el cual muestra el tiempo en segudos desde la última vez que la conexión "hizo" algo. A mayor valor, más tiempo ha estado de ociosa. La otra columna a la que hay que prestarle atención es WAIT_CLASS, que puede presentar varios valores, siendo IDLE es el nos convendría eliminar.

Con base a esta información podemos eliminar (kill) aquellas sesiones que estén inactivas, tengan un LAST_CALL_ET alto, y su WAIT_CLASS sea IDLE. Para eliminar (kill) una conexión, utilizamos el siguiente comando:

ALTER SYSTEM KILL SESSION '65,327'

Donde el primer número (67) indica la SID de la conexion, y el segundo (327) el SERIAL#. Adicionalmente, se le puede añadir la palabra INMEDIATE al final de la instrucción para ejecutar la eliminación de manera instantanea.

Por último es posible que se desee borrar de manera automática todas las conexiones que poseaan dichas características, incluso de manera periódica. Para ello es recomendable crear un script que lo haga por nosotros. Cabe resaltar, que en caso de que sea frecuente que nos pase el problema con las conexiones, lo más correcto es buscar la causa, ya sea por cuestiones de programación o de la red. Pero bueno, para hacer el borrado a la mala, podemos usar el siguiente script:

BEGIN

FOR R IN (SELECT SID, SERIAL# FROM SYS.V_$SESSION WHERE STATUS = 'INACTIVE' AND SCHEMANAME<>'SYS' )

LOOP
execute IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' ||
R:SID || ',' || R.SERIAL# || '''';
END LOOP;

END;

8 comentarios:

  1. Gracias por el tip amigo. Ojalá que sigas escribiendo sobre Oracle ... Nos echarías mucho la mano a nosotros los newbies

    ResponderEliminar
  2. Muchas Gracias por tu aporte.
    Es de gran ayuda ya que en ningun otro lado he podido encontrar una referencia parecida a la tuya para eliminar las conexiones que se quedaron vivas.

    Saludos y esperamos mas aportes tuyos.

    ResponderEliminar
    Respuestas
    1. ojo a este sistema, que este inactivo en un determinado momento no significa que 1sg despues haga algo. No utilizar el kill tan alegremente. Esto lo tiene que arreglar la parte de la aplicacion.

      Eliminar
    2. Efectivamente. Totalmente de acuerdo, se debe buscar la raíz de dicho problema. Sin embargo existen ocasiones donde tienes entornos de producción y mientras buscas el error, tienes que tener los sistemas funcionando. Esta solo es una solución temporal.

      Eliminar
    3. creo que se deberia utilizar solo cuando el status sea 'SNIPED'.

      Eliminar
  3. Muchas gracias por el aporte, me ha venido muy bien. Sólo me queda una duda, si el problema no esta en la programación, ¿que tipo de problemas de red podrían provocar que las sesiones no se cerraran correctamente?
    Muchas gracias.
    Saludos.

    ResponderEliminar
    Respuestas
    1. Hola, que bien que te fue de utilidad, aunque hace un tiempo ya que escribí esto. Y revisando tu pregunta, no se me ocurre una situación específica. En teoría Oracle debería manejar esto automáticamente. El sistema que usabamos era una bdd en Oracla con una aplicación WinForms en C# (cliente-servidor). Sin embargo viéndolo en retrospectiva, la mayoría eran errores de programación, pues si la conexión se caía durante una transacción, debería eliminar la conexión Oracle. Sin embargo, a veces parecía no suceder así.

      Eliminar
  4. hola sabes, no logro dar con WAIT_CLASS mi oracle es 10g

    ResponderEliminar