jueves, 24 de octubre de 2013

Renombrar/Realocar datafiles online

En 12c se puede renombrar o realocar datafiles sin necesidad de pasarlos a offline ni tener que hacerlo con la base montada. Esta nueva posibilidad es muy interesante ya que no tenemos que esperar a realizar este tipo de tareas, que suelen ser bastante frecuentes, fuera de horario ni en ventanas de mantenimiento.

Algunas consideraciones a tener en cuenta:
    • Se puede realocar desde y hacia distintos tipos tipos de storage (por ejemplo desde ASM hacia FS o visceversa)
    • En arquitecturas con Bases Standby se deber realizar el realocado/renombrado en forma separado en primaria y standby.
    • La realocación en entornos Windows, deja el datafile original y deber ser borrado explicatamente luego de completada la operación
    • No aplica a temporary files
    • En CDB  (Container DB) no se pueden mover datafiles que pertenecen a PDC (Pluggable DB)
Comparto un ejemplo para mostrarles el nuevo feature en acción:
Primero voy a intentar mover un datafile en 11g:

SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
SQL> select file_name from dba_data_files;

FILE_NAME
--------------------------------------------------------------------------------
/u01/app/oradata/rop/users01.dbf
/u01/app/oradata/rop/undotbs01.dbf
/u01/app/oradata/rop/sysaux01.dbf
/u01/app/oradata/rop/system01.dbf
SQL> alter tablespace users rename datafile '/u01/app/oradata/rop/users01.dbf'
2 to '/u01/app/oradata/users01.dbf';
alter tablespace users rename datafile '/u01/app/oradata/rop/users01.dbf'
*
ERROR at line 1:
ORA-01525: error in renaming data files
ORA-01121: cannot rename database file 4 - file is in use or recovery
ORA-01110: data file 4: '/u01/app/oradata/rop/users01.dbf'
Como se observa no se puede renombrar un datafile que esta ONLINE
Veamos que pasa en 12c:
Lo primero que uno prueba si solo escuchó que en 12c, y no se tomó el tiempo para leer el manual,  se puede renombrar datafiles online,  es usar la sintaxis que se usa para renombrar datafiles offline en versiones 11g e inferiores:
SQL> select banner from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
PL/SQL Release 12.1.0.1.0 - Production
CORE 12.1.0.1.0 Production
TNS for Linux: Version 12.1.0.1.0 - Production
NLSRTL Version 12.1.0.1.0 - Production

SQL> alter tablespace users rename datafile '/u01/app/oradata/rop/users01.dbf'
2 to '/u01/app/oradata/users01.dbf';
alter tablespace users rename datafile '/u01/app/oradata/rop/users01.dbf'
*
ERROR at line 1:
ORA-01525: error in renaming data files
ORA-01121: cannot rename database file 4 - file is in use or recovery
ORA-01110: data file 4: '/u01/app/oradata/rop/users01.dbf'
El error es el mismo. El tema es que para realocar datafiles se agregó una nueva sintaxis:
ALTER DATABASE MOVE DATAFILE ( 'filename' | 'ASM_filename' | file_number )
 [ TO ( 'filename' | 'ASM_filename' ) ]
 [ REUSE ] [ KEEP ]
Ahora probemos de renombrar usando la nueva sintaxis:
SQL> alter database move datafile '/u01/app/oradata/ropusers01.dbf'
2 to '/u01/app/oradata/ropusers02.dbf';

Database altered.

SQL> select file_name from dba_data_files;

FILE_NAME
--------------------------------------------------------------------------------
/u01/app/oradata/rop/users02dbf
/u01/app/oradata/rop/undotbs01.dbf
/u01/app/oradata/rop/sysaux01.dbf
/u01/app/oradata/rop/system01.dbf

El datafile se renombró online !!!

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.