Está en la página 1de 5

1 .

- Listar los bloqueos



SELECT /*+ FULL(s) PARALLEL(l, 5) */
decode(L.TYPE,'TM','TABLE','TX','Record(s)') TYPE_LOCK,
decode(L.REQUEST,0,'NO','YES') WAIT,
S.OSUSER OSUSER_LOCKER,
S.PROCESS PROCESS_LOCKER,
S.USERNAME DBUSER_LOCKER,
O.OBJECT_NAME OBJECT_NAME,
O.OBJECT_TYPE OBJECT_TYPE,
concat(' ',s.PROGRAM) PROGRAM,
O.OWNER OWNER
FROM v$lock l,dba_objects o,v$session s
WHERE l.ID1 = o.OBJECT_ID
AND s.SID =l.SID
AND l.TYPE in ('TM','TX');




2.- Del paso anterior obtengo el usuario y con esta sentencia copio el SID y SERIAL#


SELECT OSUSER, PROCESS ,SID,SERIAL# FROM V$SESSION WHERE OSUSER =
'egallegos';

3.- Con los datos anteriores elimino el proceso.

ALTER SYSTEM KILL SESSION '297,62179';

4.- Consulta de Usuario que realiza un bloqueo.

select oracle_username || ' (' || s.osuser || ')' username,
s.sid || ',' || s.serial# sess_id,
owner || '.' || object_name object,
object_type,
decode(l.block, 0, 'Not Blocking', 1, 'Blocking', 2, 'Global') status,
decode(v.locked_mode,
0,
'None',
1,
'Null',
2,
'Row-S (SS)',
3,
'Row-X (SX)',
4,
'Share',
5,
'S/Row-X (SSX)',
6,
'Exclusive',
TO_CHAR(lmode)) mode_held
from v$locked_object v, dba_objects d, v$lock l, v$session s
where v.object_id = d.object_id
and v.object_id = l.id1
and v.session_id = s.sid
order by oracle_username, session_id;


Bloqueo de tablas hijo por causa de ejecutar sentencias
PL/SQL sobre tablas padre

En versiones de la base de datos Oracle anteriores a la 9i, cuando la
clave primaria de una tabla padre (parent table) no se encuentra indexada en la tabla hijo (child table),
es muy probable que tengamosproblemas con los bloqueos de la tabla hijoque se producen, bien
cuando se actualiza (con la sentencia PLSQL UPDATE) la clave primaria de la tabla padre (lo cual ocurre
con relativa frecuencia ya que existen determinados trabajos que actualizan todas las columnas de una
tabla incluso cuando el valor de la misma no ha cambiado), o bien cuando se realizaba el borrado (con la
sentencia PL/SQL DELETE) de algn registro de la tabla padre.

El caso es que en las circunstancias anteriores y para evitar que se produzca un bloqueo completo de la
tabla hijo (full table lock), lo ms recomendable es indexar tambin en la tabla hijo la clave primaria de
la tabla padre. No obstante, esta norma de bloqueo cambi con la versin 9i de la base de datos Oracle.

La norma en Oracle 9i, aunque bsicamente el bloqueo completo no se puede evitar, lo que s que hace
es disminuir sensiblemente el tiempo que dura dicho bloqueo. As, para versiones de la base de datos
Oracle posteriores a la 9i, si se actualiza o se borra algn registro de una tabla padre cuya clave primaria no
est indexada en la tabla hijo, dicha tabla hijo queda totalmente bloqueada slo mientras dura la ejecucin
de las sentencias PLSQL UPDATE o DELETE. Es decir, el bloqueo se libera cuando las sentencias
terminan y no es necesario esperar a que se ejecute la sentencia PL/SQL COMMIT. Por lo tanto, aunque la
situacin es mejor que para versiones anteriores a Oracle 9i, el bloqueo completo de la tabla hijo todava
ocurre.

Tambin conviene sealar que este bloqueo completo de la tabla hijo tambin ocurre cuando se ejecuta
la sentencia PLSQL MERGE (sentencia que apareci precisamente con la versin de la base de datos
Oracle 9i). No obstante, despus de la versin Oracle 11g Release 1, la ejecucin de una sentencia PL/SQL
MERGE no siempre produce el bloqueo de la tabla hijo, esto ocurre cuando el MERGE es simplemente un
INSERT, o cuando el MERGE funciona tambin como un UPDATE pero dicho UPDATE no cambia la clave
primaria de la tabla padre.

A continuacin os dejo un script SQL con el que es posible detectar las claves primarias que no estn
indexadas en las tablas hijo correspondientes (por cierto, en ingls las claves primarias de una tabla
padre se conocen, desde el punto de vista de las tablas hijos, como foreign keys o claves extranjeras). El
script slo funciona para claves primarias que incluyen un mximo de ocho columnas.
SELECT nombre_tabla,
nombre_constraint,
cnom1 || NVL2(cnom2,','||cnom2,NULL) ||
NVL2(cnom3,','||cnom3,NULL) ||
NVL2(cnom4,','||cnom4,NULL) ||
NVL2(cnom5,','||cnom5,NULL) ||
NVL2(cnom6,','||cnom6,NULL) ||
NVL2(cnom7,','||cnom7,NULL) ||
NVL2(cnom8,','||cnom8,NULL) columnas
FROM ( SELECT uc.table_name nombre_tabla,
uc.constraint_name nombre_constraint,
MAX(DECODE(pos,1,coln,NULL)) cnom1,
MAX(DECODE(pos,2,coln,NULL)) cnom2,
MAX(DECODE(pos,3,coln,NULL)) cnom3,
MAX(DECODE(pos,4,coln,NULL)) cnom4,
MAX(DECODE(pos,5,coln,NULL)) cnom5,
MAX(DECODE(pos,6,coln,NULL)) cnom6,
MAX(DECODE(pos,7,coln,NULL)) cnom7,
MAX(DECODE(pos,8,coln,NULL)) cnom8,
count(*) ncol
FROM ( SELECT SUBSTR(table_name,1,30) tn,
SUBSTR(constraint_name,1,30) cn,
SUBSTR(column_name,1,30) coln,
position pos
FROM user_cons_columns ) ucc,
user_constraints uc
WHERE ucc.cn = uc.constraint_name
AND uc.constraint_type = 'R'
GROUP BY uc.table_name, uc.constraint_name
) user_cons
WHERE ncol > ALL
( SELECT count(*)
FROM user_ind_columns uic
WHERE uic.table_name = user_cons.nombre_tabla
AND uic.column_name in (cnom1, cnom2,
cnom3, cnom4,
cnom5, cnom6,
cnom7, cnom8)
AND uic.column_position <= user_cons.ncol
GROUP BY uic.index_name
)

En conclusin, la clara recomendacin que personalmente doy es que, si sobre una tabla padre vamos a
realizar operaciones de actualizacin de la clave primaria, borrado de registros o merge (insercin +
actualizacin + borrado), lo mejor es proceder a indexar dicha clave primaria en la tabla hijo. Adems,
otra circunstancia que hace recomendable la indexacin de la clave primaria de la tabla padre en la tabla
hijo, es que no hacerlo puede derivar en graves problemas de rendimiento.






Las claves forneas producen bloqueos en Forms?
La respuesta es que si no hacemos bien las cosas es SI. Vamos a verlo mejor con un ejemplo con las
tpicas tablas de formacin que utiliza Oracle, DEPT y EMP:

CREATE TABLE dept (
deptno NUMBER(2) NOT NULL CONSTRAINT dept_pk PRIMARY KEY,
dname VARCHAR2(14),
loc VARCHAR2(13));

CREATE TABLE emp (
empno NUMBER(4) NOT NULL CONSTRAINT emp_pk PRIMARY KEY,
ename VARCHAR2(10),
job VARCHAR2(9),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2) CONSTRAINT emp_ref_dept_fk
REFERENCES dept(deptno));

Insertamos un departamento:

INSERT INTO dept (deptno, dname, loc)
VALUES (23, 'CONTABILIDAD', 'VIGO');

COMMIT;

Ahora insertamos un empleado:

INSERT INTO emp (empno,ename,job,mgr,
hiredate,
sal,comm,deptno)
VALUES (1234, 'MARIOBROS', 'FONTA', 10,
TO_DATE('16/05/1975', 'DD/MM/YYYY'),
50000, 2000, 23);


Antes de hacer el commit, al ver los bloqueos veremos que estn la tabla EMP y la DEPT bloqueadas.

SELECT lk.sid, lk.TYPE lock_type, lk.lmode,
(SELECT o.object_name
FROM dba_objects o
WHERE o.object_id = lk.id1) object_name
FROM gv$lock lk
WHERE lk.TYPE IN ('TM', 'UL');

Lo que nos devolver ser esto:

SID LO LMODE OBJECT_NAME
------ -- --------- ----------------
311 TM 3 EMP
311 TM 3 DEPT

El bloqueo de la tabla EMP es por el registro que acabamos de insertar pero que todava no est
commitado, pero la tabla DEPT se bloquea por la clave fornea, ya que en el momento de insertar el
registro en EMP exista el departamento 23 en DEPT, pero como no hemos comitado el insert en EMP tiene
que bloquear el registro del departamento 23 para evitar que otra sesin borre ese registro o modifique el
cdigo del departamento.

Hasta aqu todo normal, el problema viene cuando otra sesin quiere modificar el nombre del departamento:

UPDATE dept
SET dname = 'FINANCIERO'
WHERE deptno = 23;

Con esta update nos dejar modificarlo sin problema, pero si en vez de hacer un update que nicamente
modifica el nombre del departamento hacemos este otro (el resultado final de los datos en la tabla sern los
mismos):

UPDATE dept
SET deptno = 23,
dname = 'FINANCIERO',
loc = 'VIGO'
WHERE deptno = 23;

El registro quedara con los mismos datos, pero ya tenemos el bloqueo montado ya que le estamos diciendo
que actualice el campo DEPTNO, pero la modificacin de ese campo afectara a registros introducidos por
otra sesin y que todava no estn comitados, por lo que se quedar bloqueado.

Esta es la explicacin del motivo, pero porqu ocurre en Forms?. La respuesta la encontramos en la
propiedad "Actualizar Slo Columnas Cambiadas" a nivel de bloque, por defecto esa propiedad est a "No"
con lo que para hacer un update actualizar todos los campos, incluso los que no ha modificado el usuario.

Lo recomendable para evitar bloqueos es poner esa propiedad al valor "Si".

También podría gustarte