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 más recomendable es indexar también en la tabla hijo la clave primaria de la tabla padre. No obstante, esta norma de bloqueo cambió con la versión 9i de la base de datos Oracle.
La norma en Oracle 9i, aunque básicamente 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 algún registro de una tabla padre cuya clave primaria no está indexada en la tabla hijo, dicha tabla hijo queda totalmente bloqueada sólo mientras dura la ejecución 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 situación es mejor que para versiones anteriores a Oracle 9i, el bloqueo completo de la tabla hijo todavía ocurre.
También conviene señalar que este bloqueo completo de la tabla hijo también ocurre cuando se ejecuta la sentencia PLSQL MERGE (sentencia que apareció precisamente con la versión de la base de datos Oracle 9i). No obstante, después de la versión Oracle 11g Release 1, la ejecución 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 también como un UPDATE pero dicho UPDATE no cambia la clave primaria de la tabla padre.
A continuación os dejo un script SQL con el que es posible detectar las claves primarias que no están indexadas en las tablas hijo correspondientes (por cierto, en inglés 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 sólo funciona para claves primarias que incluyen un máximo de ocho columnas.
En conclusión, la clara recomendación que personalmente doy es que, si sobre una tabla padre vamos a realizar operaciones de actualización de la clave primaria, borrado de registros o merge (inserción + actualización + borrado), lo mejor es proceder a indexar dicha clave primaria en la tabla hijo. Además, otra circunstancia que hace recomendable la indexación de la clave primaria de la tabla padre en la tabla hijo, es que no hacerlo puede derivar en graves problemas de rendimiento.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 )
2 comentarios:
Excelente tip!! hace ya un tiempo que venia observando este tipo de bloqueos en mi sistema... gracias crack!!
Hola, como siempre un gusto leer tus articulos.
Y si, tienes toda la razon, la regla de oro aqui es: Toda FK en un tabla TIENE que tener un indice asociado, de lo contrario van a sufrir sobre todo en aplicaciones que manejan alto nivel de concurrencia sobre las mismas tablas.
Otro detalle a tener en cuenta son los indices BITMAP, ojo con ellos en aplicaciones concurrentes pues tambien producen bloqueos.
Saludos cordiales
Jacqueline
Publicar un comentario