jueves, 20 de junio de 2013

Como, Cuándo y Por qué se invalidan objetos de bases de datos Oracle

La invalidación de objetos de bases de datos pueden ser de dos tipos:  1) invalidaciones por error de sintaxis o de alcance, es decir por un error en la escritura de código sql o pl/sql o por falta de permisos sobre objetos referenciados en otros esquemas y 2) invalidaciones por dependencias. Esta nota se va a centrar principalmente en el segundo tipo ya que estas invalidaciones son mas complicadas de anticipar y suelen ocasionar cancelaciones de procesos batch o errores en aplicativos en forma imprevista.

El primer tipo de invalidación se da cuando, por ejemplo, un objeto de código pl/sql (function, procedure, package, type o trigger) compila con errores, ya sea porque hay errores de escritura o porque un objeto que se referencia no existe o no se tiene alcance al mismo, es decir faltan privilegios. Hay que recordar que los privilegios deben ser otorgados en forma directa, y no mediante roles, ya que por definición los roles se deshabilitan en tiempo de ejecución de las unidades de código. En el caso de las vistas, que se definen en base a una sentencia sql, los errores mas comunes son referencias a columnas que no existen, ya sea porque se escribieron mal cuando se armó la vista o por cambios de definición en la tablas subyacentes. Oracle 11g permite tener una dependencia de granularidad mas fina que minimiza estos tipos de errores.

En el segundo tipo de invalidación, Oracle maneja las dependencias locales, y algunas remotas,  automáticamente, si un objeto A que depende de otro objeto B y el objeto B se invalida, el objeto A, al ser dependiente, se invalidará. Una vez que el objeto B se valide el objeto B no se validará hasta su próxima ejecución.  Este enfoque evita recompilaciones innecesarias, ya que en el transcurso de un despliegue un objeto podría requerir multiples recompilaciones, pero por otro lado hay que ser muy cuidadoso en sistemas de alta transaccionabilidad (OLTP) ya que si se deja que el objeto se valide automáticamente al referenciarse por primera vez, y si esta invocación ocurre durante un pico de actividad de la base se podría ocasionar un lockeo en memoria (latch).  

Las invalidaciones por dependencias mas problematicas son las que se dan por dependencias remotas, es decir las que se producen sobre objetos que referencian objetos remotos via dblinks. Dichas dependencias estan gobernadas por el parámetro remote_dependencies_mode que puede tener los siguientes valores: TIMESTAMP (default) y SIGNATURE. Es importante aclarar que Oracle solo maneja dependencias entre objetos de código, por ejemplo, Si un procedure Px en BD1 referencia una tabla remota T1 en B2 y la tabla se elimina, Px nunca se invalida (en vista dba_objects la columna status siempre será VALID para Px), por otro lado, si un procedure Px en BD1 referencia un procedure Py en BD2 y Py se invalida, entoces Px se invalidará en la próxima ejecución. 
   

Modo Timestamp

  • Cada vez que un procedimiento local llama a un procedimiento remoto, Oracle compara el timestamp que el primero local tiene del segundo y lo compara con el timestamp corriente del procedimiento remoto. Si los dos timestamp coinciden, ambos procedimientos se ejecutan.
  • Si los timestamps no coinciden, el procedimiento local se invalida y se retorna un error al entorno que lo invocó.
  • Cuando se compila un objeto dependiente se registra el timestamp de todos los procedimientos referenciados.
  • El procedimiento local se invalida recién cuando se invoca el procedimiento remoto inválido por lo cual las sentencias que precedieron a la llamada corren normalmente.
  • Las DML ‘s que precedieron la llamada que invalida al procedimiento local solo se “rollbackean” si están en el mismo bloque pl. 
     
Modo Signature


Un RPC Signature cambia cuando al menos uno de los siguientes cambios son efecuados:
  • Nombre
  • Número de parámetros
  • Tipo de datos de los parámetros
  • Modo de cada parámetro
  • Tipo de datos de valor de retorno (en funciones)
     
Para minimizar errores por dependencias remotas
  1. No abusar del uso de dblinks
  2. Declarar los registros con el atributo %ROWTYPE
  3. Declarar las variables con el atributo %TYPE
  4. Incluir la lista de columnas en los INSERT y SELECT
  5. Paquetizar los procedimientos y funciones
  6. Evitar realizar compilaciones en la ventana online
  7. Agregar nuevos procedimientos/funciones al final del paquete.
  8. Recompilar dependencias de primer y segundo nivel luego de cada nuevo desplique en BD.
     
Tipificación de Invalidaciones por Dependencias

El siguiente cuadro muestra los distintos escenarios de dependencias entre objetos y como Oracle resuelve cada uno:



Claramente el caso 4 es el mas complicado. Este tipo de error se puede dar cuando, por ejemplo, una implementación nocturna sobre una base ocasiona errores al día siguiente sobre otra base que tiene objetos que referencian a objetos implementados o dependendientes localmente de los implementados, y al ejecutarse por primera vez se invalida y queda en ese estado hasta que un dba realice una compilación manual. Hay que tener en cuenta que Oracle no invalida objetos remotos hasta que se ejecutan, lo cual hace difícil medir el impacto que tendrá la nueva implementación sobre objetos dependientes. Para clarificar voy a mostrar un ejemplo de este caso:


Sesion 1 BD1
Sesion 2  BD2
Descripción
T0
create or replace procedure sp_bd1
is
   begin
       sp_bd2@testinv;
   end;
create or replace procedure sp_bd2
 is
    cnt int;
    begin
        select count(1) into cnt from t;
    end;

T1
VALID 
2012-11-14 14:41:44
2012-11-14:14:41:44
VALID  
2012-11-14 14:35:23
2012-11-14:14:35:23

T2

alter table t rename to u;
Se renombra la tabla referenciada por sp_bd2 para que se invalide
T3
VALID 
2012-11-14 14:41:44
2012-11-14:14:41:44
INVALID
2012-11-14 14:35:23
2012-11-14:14:35:23

T4
SQL> exec sp_bd1;
BEGIN sp_bd1; END;
*
ERROR en linea 1:
ORA-04063: procedure "ROP.SP_BD2" tiene errores
ORA-06512: en "ROP.SP_BD1", linea 4
ORA-06512: en linea 1

Falla la ejecución de sp_bd1 porque el objeto remoto referenciado esta invalido
T5
INVALID
2012-11-14 14:41:44
2012-11-14:14:41:44
INVALID
2012-11-14 14:38:50
2012-11-14:14:38:50
Con la ejecución de sp_bd1 cambió el last_ddl y el timestamp del sp referenciado en sp_bd2 y se invalidó sp_bd1
T6
SQL>  exec sp_bd1;
BEGIN sp_bd1; END;
      *
ERROR en linea 1:
ORA-06550: linea 1, columna 7:
PLS-00905: el objeto ROP.SP_BD1 no es valido
ORA-06550: linea 1, columna 7:
PL/SQL: Statement ignored

Al ejecutar la segunda vez cambia el mensaje de error ya que el objeto ahora esta invalido.
T7
INVALID
2012-11-14 14:49:50
2012-11-14:14:49:50
INVALID
2012-11-14 14:38:50
2012-11-14:14:38:50
Cambió el last_dd y el timestamp de sp_bd1 y no el de sp_bd2
T8

alter table u rename to t
Se renombra la tabla a su  nombre original, que es el usado en sp_bd2
T9
INVALID
2012-11-14 14:49:50
2012-11-14:14:49:50
INVALID
2012-11-14 14:38:50
2012-11-14:14:38:50
Si bien ahora no hay errores ni el sp local ni el remoto detectaron el cambio y siguen invalidos con los mismas fechas
T10

SQL> exec sp_bd2;
Se ejecuta el sp_bd2 y no da errores
T11
INVALID
2012-11-14 14:49:50
2012-11-14:14:49:50
VALID 
2012-11-14 14:49:20
2012-11-14:14:49:20
Al ejecutarse y no tener mas errores el sp se compila automáticamente con la primera invocación. (validación local transparente). El sp_bd1 sigue invalido
T12
SQL>  exec sp_bd1;
BEGIN sp_bd1; END;
      *
ERROR en linea 1:
ORA-06550: linea 1, columna 7:
PLS-00905: el objeto ROP.SP_BD1 no es valido
ORA-06550: linea 1, columna 7:
PL/SQL: Statement ignored

Se ejecuta el sp_bd1 y da error porque esta invalido y no se valida automáticamente, aunque se vuelva a ejecutar mas de una vez
T13
INVALID
2012-11-14 14:49:50
2012-11-14:14:49:50


T14
alter procedure sp_bd1 compile;

Se compila manualmente sp_bd1
T15
VALID  
2012-11-14 15:00:22
2012-11-14:15:00:22

El procedimiento requirió compilación manual para validarse.

No hay comentarios:

Publicar un comentario