Eliminar bloqueos en la base de datos

Si detectamos que la base de datos tiene un rendimiento muy pobre y que funciona de forma muy lenta, es posible que estemos experimentando bloqueos. Si esto ocurre deberemos eliminar los bloqueos en la base de datos para que ésta vuelva a funcionar con normalidad.

¿Qué son los bloqueos y por qué ocurren?

Según la propia documentación de Oracle, los bloqueos son mecanismos que evitan la interacción destructiva entre transacciones que acceden al mismo recurso, ya sean objetos (como tablas y filas) u objetos del sistema (como estructuras de datos compartidas en la memoria y filas del diccionario de datos).

Es decir, que podemos experimentar bloqueos si Oracle detecta, por ejemplo, que dos usuarios están actualizando un mismo recurso.

Detectar los bloqueos

Como decía en la introducción, detectar un escaso rendimiento en la base de datos es un indicativo de que podemos estar sufriendo bloqueos. Podemos listar todos los bloqueos con la siguiente sentencia:

select distinct
a.sid "waiting sid"
, a.event
, c.sql_text "SQL from blocked session"
, b.sid "blocking sid", b.username, b.machine
, b.event
, b.sql_id
, b.prev_sql_id
, d.sql_text "SQL from blocking session"
from v$session a, v$session b, v$sql c, v$sql d
where a.event='enq: TX - row lock contention'
and a.blocking_session=b.sid
and c.sql_id=a.sql_id
and d.sql_id=nvl(b.sql_id,b.prev_sql_id);

Esto nos devolverá una fila por cada bloqueo que estemos sufriendo en la base de datos, así como la información del usuario, máquina y sentencia que los han generado. Muy útil para descubrir el problema. Recomiendo guardar esta información (por ejemplo desde SQLDeveloper podemos exportarla como HTML) por si en un futuro tenemos que dar explicaciones o señalar al culpable.

Eliminar los bloqueos

Una vez tenemos claro que estamos sufriendo bloqueos, es hora de eliminarlos. Para ello tenemos que matar la sesión del usuario bloqueador, esto normalmente se hace de la siguiente forma:

ALTER SYSTEM KILL SESSION '<sid, serial#>';

Pero aquí lo vamos a simplificar, ya que este blog está creado con la final de ayudar a todos los administradores de bases de datos. El siguiente comando detectará los bloqueos activos y generará directamente la sentencia con la que podréis eliminar los bloqueos, simplemente lanzad el resultado que os devuelva y lo tendréis hecho:

SELECT l1.sid, ' IS BLOCKING ', l2.sid ,  'alter system kill session '''||l1.sid||','||s3.serial#||''' immediate;'
FROM v$lock l1, v$lock l2, v$session s3
WHERE l1.BLOCK =1 AND l2.request > 0
AND l1.id1=l2.id1
AND l1.id2=l2.id2
AND l1.sid= s3.sid;

Con esto me despido, espero y deseo que os haya servido.

Deja un comentario