domingo, 27 de abril de 2025

Manejando las Transacciones Bloqueadas

Objetivos:

 Describir las Secciones de Oracle.
 Consultar las secciones activas.
 Conocer los metodos para terminar y/o desconectar las sesiones activas.
 Ver y terminar los bloqueos de Transacciones.






_______________________________________________________________________
Las Sesiones de Oracle.

Una sesión no es más que la conexión entre una aplicación X y la Base de Datos Oracle con sus respectivos objetos.

Puede consultar y obtener información de las sesiones de Oracle mediante las vistas V$SESSION GV$SESSION. Estas vistas contienen entre otros, los campos sid, serial#, inst_id útiles para dropear las secciones.

SELECT
        vs.sid
        , vs.serial#
        , vs.*
FROM    sys.v$session vs
;

SELECT
        gvs.sid
        , gvs.serial#
        , gvs.inst_id
        , gvs.*
FROM    sys.gv$session gvs
;

_______________________________________________________________________
Los Bloqueos de Oracle.

Oracle ofrece varias vistas que permiten consultar los bloqueos de transacciones sobre los distintos objetos de base de datos. Una de ellas es la vista V$LOCK, esta muestras los bloqueos activos en la base de datos sin muchos detalles del objeto bloqueado.

A continuación un ejemplo de la utilidad de la vista V$LOCK:

    1. Conectado con HR ejecutamos la consulta:
SELECT
        employee_id
        , first_name
        , last_name
        , email
FROM    hr.employees
WHERE   employee_id =   100
;








    2. Actualizamos el campo email, no ejecutamos COMMIT alguno y re ejecutamos la anterior consulta:
UPDATE  hr.employees
    SET email   =   email||'@company.com'
WHERE   employee_id =   100
;






    3. Conectado con un segundo usuario (SYSTEM en mi caso) ejecutamos los mismos script anteriores:





















/*Debido a que el usuario HR no ejecutó COMMIT luego del UPDATE, esa transacción está pendiente y ningun otro usuario puede ver los cambios.*/

    4. Con el usuario SYSTEM tratamos de actualizar el mismo campo email para el empleado 100 y notamos como la transacción no se completa debido al bloqueo del registro:














    5. Ahora conectado con un tercel usuario (SYS en mi caso) ejecutamos la siguiente consulta:

SELECT
        (
            SELECT  s.username
            FROM    sys.v$session s
            WHERE   s.sid=bker.sid
        )           AS  usuario_bloqueador,
        bker.SID    AS  sid_bloqueador,
        (
            SELECT  s.username
            FROM    sys.v$session s
            WHERE   s.sid=bked.sid
        )           AS  usuario_bloqueado,
        bked.SID    AS  sid_bloqueado
FROM
        sys.v$lock bker
        JOIN    sys.v$lock bked
            ON  (
                bker.id1 = bked.id1
                AND     bker.id2 = bked.id2
                )
WHERE
        bker.block = 1
AND     bked.request > 0
;





_______________________________________________________________________
La Vista V$LOCKED_OBJECT
La vista V$LOCKED_OBJECT permite ver las transacciones bloqueadas en la Base de Datos con más detalle, permitiendo conocer el objeto bloqueado.

La siguiente consulta muestra las mismas sesiones bloqueadas con el objeto que contiene el bloqueo:

SELECT
        o.owner||'.'||o.object_name     AS  objeto
        ,o.object_type                  AS  tipo_bojeto
        ,s.username                     AS  usuario_conexion
        ,s.sid
        ,s.serial#
        ,s.status
        , DECODE(s.status, 'INACTIVE', 'BLOQUEADOR', 'ACTIVE', 'BLOQUEDADO', 'DESCONOCIDO') AS  DESR_USUARIO
FROM
        sys.gv$locked_object bo
        JOIN    sys.gv$session s
            ON  ( s.sid = bo.session_id)
        JOIN    sys.dba_objects o
            ON  (bo.object_id    =   o.object_id
                    AND bo.inst_id      =   s.inst_id)
;






_______________________________________________________________________
Eliminando Bloqueos de Base Datos
Oracle ofrece varios métodos para desbloquear una transacción. Puede utilizar las sentencias:

    ALTER SYSTEM KILL SESSION 'SID, SERIAL#' [IMMEDIATE];

La anterior sentencia revierte las transacciones en curso, libera los bloqueos y recupera parcialmente los recursos utilizados; si no incluimos la clausula IMMEDIATE la sesión es marcada como 'marked for kill' para que ésta se elimine tan pronto como le sea posible, teniendo en cuenta que dicho proceso puede tomar varios minutos en completarse. 

    ALTER SYSTEM DISCONNECT SESSION 'SID, SERIAL#' [POST_TRANSACTION IMMEDIATE];

La pasada sentencia es un método alternativo para eliminar transacciones bloqueadas. Mientras que KILL SESSION solicita a la sesión que se auto elimine automáticamente, DISCONNECT SESSION termina el proceso del servidor dedicado. Lo que es igual a terminar el proceso desde el sistema operativo.

La cláusula POST_TRANSACTION espera a que se completen las transacciones en curso para luego desconectar la sesión, la cláusula IMMEDIATE desconecta la sesión y las transacciones en curso se revierten inmediatamente.

Tener pendiente que en la sintaxis [ ]  indica que ambas cláusulas son opcionales, pero esto no es así, se deben especificar una o ambas, de lo contrario recibiría un error. Si ambas cláusulas son incluidas IMMEDIATE seria ignorada.

ALTER SYSTEM KILL SESSION '1473, 24750' IMMEDIATE;

ALTER SYSTEM DISCONNECT SESSION '1473, 24750' IMMEDIATE;
/*Las dos sentencias anteriores muestran un ejemplo de como terminar la sesión bloqueadora.*/


DECLARE

    CURSOR  cur_sessions    IS
        SELECT
                vs.sid
                , vs.serial#
        FROM    sys.v$session vs
        WHERE   sid <>   SYS_CONTEXT('USERENV', 'SID')
        ;

BEGIN

    FOR i   IN  cur_sessions    LOOP
    BEGIN
        EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION '''||i.sid||', '||i.serial#||''' IMMEDIATE';

    EXCEPTION
    WHEN OTHERS THEN
        BEGIN
            EXECUTE IMMEDIATE 'ALTER SYSTEM DISCONNECT SESSION '''||i.sid||', '||i.serial#||''' IMMEDIATE';

        EXCEPTION
            WHEN OTHERSTHEN
                NULL;
        END;
    END;
    END LOOP;

END;
/*El bloque PL/SQL anterior consulta todas las sesiones de base de datos diferentes a la sesión actual y utiliza las sentencias KILL SESSION y DISCONNECT SESSION para eliminarlas o desconectarlas .*/


Fuentes 
https://docs.oracle.com/cd/B14099_19/web.1012/b15901/sessions001.htm
https://dbaora.com/kill-session-in-oracle/
https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/V-LOCK.html
https://oracle-base.com/articles/misc/killing-oracle-sessions