viernes, 28 de diciembre de 2018

LogMiner Ver el contenido Logfile y archivelog.


LogMiner es una  utilidad de Oracle para examinar el contenido de los archivos redolog y archivelogs, como sabemos en los redologs son almacenan todos los cambios realizados en la base de datos y sirven para la recuperación de la base de datos en caso de un fallo del sistema manejador de base de datos RDBMS, los archevelogs son los redologs almacenados de forma histórica y sirven para recuperaciones de base de datos en conjunto con el backup RMAN.

Para que nos sirve esta utilidad:
  • Determinar cuando pudo ocurrir  una corrupción lógica en una base de datos, como errores cometidos en el nivel de la aplicación.
  • Determinar qué acciones tendría que realizar para realizar una recuperación detallada en el nivel de transacción.
  • Ajuste del rendimiento y planificación de la capacidad a través del análisis de tendencias.
  • Realice un seguimiento de cualquier DML(Insert, update, delete) y  (Create, alter, drop) ejecutados en la base de datos, el orden en que se ejecutaron y quién los ejecutó.


Como podemos examinarlos?
Bueno para esto es mejor un ejemplo examinando los redologs, para esto vamos a realizar unas operaciones DDL(Create table) y DML (Insert).

create table prueba_log_miner
(
    campo1  number,
    campo2 varchar2(30),
    campo3 date
);

insert into prueba_log_miner values(1,'PRUEBA LOGS',sysdate);

commit;

Luego de ejecutar las sentencias ahora hay que determinar cual es el grupo de redolog activo donde se almaceno el registro de la modificación., luego ubicamos los archivos miembros del grupo y copiamos uno de ellos.

Ver el grupo activo
SELECT GROUP#, ARCHIVED, STATUS FROM V$LOG;



Vemos que el grupo 2 es el activo, ahora seleccionar unos de los archivos miembros del grupo numero 2

SELECT GROUP# "GROUP", STATUS, MEMBER , TYPE FROM SYS.V_$LOGFILE WHERE GROUP# =2;


Ahora si vamos a usar las utilidades DBMS_LOGMNR
--Se indica el archivo que se cargara los logs almacenados
Begin
  SYS.DBMS_LOGMNR.ADD_LOGFILE( 'E:\ORACLE\DATA\BASE\ONLINELOG\G2_REDO01.LOG',
 sys.dbms_logmnr.New);
end;

--Se realiza la carga del archivo al diccionario.
Begin
  SYS.DBMS_LOGMNR.START_LOGMNR
  (
   Options => sys.dbms_logmnr.DICT_FROM_ONLINE_CATALOG
  );
end;

sys.dbms_logmnr.New Usamos para indicar que se realizara una carga nueva si es un solo archivo, pero si vamos a incluir más de uno el siguiente archivo se pondría el sys.dbms_logmnr.Addfile, con esto podemos ver mas de un archivo en el diccionario.

Ahora revisamos el contenido de los logs en la vista V$LOGMNR_CONTENTS
Select  timestamp , session# , operation, sql_redo
From V$LOGMNR_CONTENTS
where sql_redo like '%prueba_log_miner%' or sql_redo like '%PRUEBA_LOG_MINER%'
Order by 1 desc





Listo, podemos ver el contenido del redo log. Ahora como podemos ver el contenido del archivelog? Bueno es el mismo procedimiento, pero debemos ubicar la ruta de los archivelogs.

Previo a esto debe de estar la base de datos en modo ARCHIVELOG, vamos a generar unos tres switch de log para forzar al archivado de los redologs.

ALTER SYSTEM SWITCH LOGFILE;
ALTER SYSTEM SWITCH LOGFILE;
ALTER SYSTEM SWITCH LOGFILE;

Ahora revisamos el archivelog generado
select STAMP, NAME, FIRST_TIME  from V$ARCHIVED_LOG where FIRST_TIME>=sysdate -1 order by 1 desc  ;




Tomamos los archivos  generados para incluirlos en el script
Begin
  SYS.DBMS_LOGMNR.ADD_LOGFILE( 'E:\ORACLE\BACKUP\BASE\ARCHIVELOG\LOG_D7IPROD_1662_0955901488_0001.ARC',
 sys.dbms_logmnr.New);
  SYS.DBMS_LOGMNR.ADD_LOGFILE( 'E:\ORACLE\BACKUP\BASE\ARCHIVELOG\LOG_D7IPROD_1663_0955901488_0001.ARC',
 sys.dbms_logmnr.Addfile);
  SYS.DBMS_LOGMNR.ADD_LOGFILE( 'E:\ORACLE\BACKUP\D7ITEST\ARCHIVELOG\LOG_D7IPROD_1664_0955901488_0001.ARC',
 sys.dbms_logmnr.Addfile);
end;

Begin
  SYS.DBMS_LOGMNR.START_LOGMNR
  (
   Options => sys.dbms_logmnr.DICT_FROM_ONLINE_CATALOG
  );
end;

Realizamos el select
Select
 timestamp ,
 operation,
 sql_redo
From V$LOGMNR_CONTENTS
where sql_redo like '%prueba_log_miner%' or sql_redo like '%PRUEBA_LOG_MINER%'
Order by 1 desc;





Listo, podemos revisar las sentencias ejecutadas.

Referencias
https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_logmnr.htm#CCHEGJCG

viernes, 21 de diciembre de 2018

Funciones Analiticas de Oracle


A veces se nos ha presentado requerimientos de presentación de información que no teníamos ni idea hacerlo. Para los SQL FANS, les presento algunas funciones muy útiles en el ámbito analítico para la elaboración de consultas SQL.

Para el uso de esta funciones hay que conocer las clausulas OVER y PARTITION BY, favor lean “Consultas SQL con la utilidad OVER(PARTITION BY”, claro que en este articulo lo explicaremos brevemente.

OVER utilidad para utilizar funciones de grupo a nivel de fila sin GROUP BY el PARTITION BY especificamos como se establecerá la agrupación.

Script para ejemplos

CREATE TABLE emp (
  empno    NUMBER(4) CONSTRAINT pk_emp PRIMARY KEY,
  ename    VARCHAR2(10),
  job      VARCHAR2(9),
  mgr      NUMBER(4),
  hiredate DATE,
  sal      NUMBER(7,2),
  comm     NUMBER(7,2),
  deptno   NUMBER(2)
);

INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87','dd-mm-rr')-85,3000,NULL,20);
INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
INSERT INTO emp VALUES (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,to_date('13-JUL-87', 'dd-mm-rr')-51,1100,NULL,20);
INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
COMMIT;



RANK.
Como su nombre lo indica es una función para ranquear las filas de datos de una consulta de acuerdo a un orden de los datos  y agrupación.

Para más claridad un ejemplo, tenemos la tabla emp y deseamos sacar los datos ranqueado por sueldo por cada departamento.

SELECT ENAME,
       DEPTNO,
       SAL,
       RANK() OVER (PARTITION BY DEPTNO ORDER BY SAL) AS RANKING
FROM   EMP;

En la consulta se agrega fila con el RANK dentro del OVER especificamos como va agrupar los datos y a continuación el orden para el RANKING.




En el resultado se muestra los datos agrupados por DPTONO (PARTITION BY DEPTNO), mostrando los datos ordenados por el salario en forma ascendente y al final el RANKING del salario.

Noten que para departamento 20 tanto SCOTT y FORD tienen el mismo RANKING ya que poseen el mismo salario.

Ahora si en vez de hacer el ranking del salario lo queremos hacer del mayor a menor en vez de menor a mayor solo agregamos DESC en el ORDER BY .

SELECT ENAME,
       DEPTNO,
       SAL,
       RANK() OVER (PARTITION BY DEPTNO ORDER BY SAL DESC) AS RANKING
FROM   EMP;



Listo ahora tenemos el rankin del mejor salario al menor salario agrupado por empresa.

DENSE_RANK
Es similar a la RANK sino que aquí el rankin se aplica de forma consecutiva.

SELECT ENAME,
       DEPTNO,
       SAL,
       DENSE_RANK() OVER (PARTITION BY DEPTNO ORDER BY SAL) AS DENSE_RANKING
FROM   EMP;

Noten que el rankin asignado se repite en fila con datos iguales para MARTIN y WARD y TURNER tiene la numeración siguiente del ranking.



Comparemos RANK y DENSE_RANK

SELECT ENAME,
       DEPTNO,
       SAL,
       RANK() OVER (PARTITION BY DEPTNO ORDER BY SAL DESC) AS RANKING,
       DENSE_RANK() OVER (PARTITION BY DEPTNO ORDER BY SAL DESC) AS DENSE_RANKING
FROM   EMP;


Si se fijan ambos dan el mismo ranking de datos pero el siguiente rankin RANK  da el valor 3  y DENSE_RANK da el consecutivo de 1 que el  2.

FIRST y LAST
Esta funcionalidad nos permite extraer el primero o último dato de una partición de datos en particular.

Como haríamos si deseamos obtener una consulta de datos de empleados que me muestre una columna del salario de la primera contratación y otra con el salario de la ultima contratación por grupo.



Vemos que el resultado tenemos por cada fila el primer salario y último salario según la fecha de ingreso por departamento. Como vemos en esta consulta evaluamos un campo pero retornamos otro.


LAG
Es una función analítica que proporciona acceso a más de una fila de una tabla al mismo tiempo Dada una serie de filas devueltas de una consulta y una posición del cursor, LAG proporciona acceso a una fila en un desplazamiento físico dado antes de esa posición.

Hagamos un ejemplo, realizaremos una consulta que extraiga el salario del empleado más otra columna con el salario previo.

SELECT EMPNO,
       DEPTNO,
       HIREDATE,
       SAL,
       LAG(SAL, 1, 0 ) OVER (ORDER BY HIREDATE) AS PREV_SAL
FROM   EMP
ORDER BY HIREDATE;


 Como vemos, la consulta esta ordenada por fecha de contratación y muestra los salarios. Adicional a esto presenta PREV_SAL que el salario anterior a los datos retornados.

LAG recibe 3 parámetros, el campo a retornar, la fila previa a retornar y el valor a retornar en caso de no existir.

Ahora hagamos el mismo ejemplo pero agrupado por departamento. Para que por orden de departamento presente la información.

SELECT EMPNO,
       DEPTNO,
       HIREDATE,
       SAL,
       LAG(SAL, 1, 0 ) OVER (PARTITION BY DEPTNO ORDER BY HIREDATE) AS PREV_SAL
FROM   EMP
ORDER BY DEPTNO, HIREDATE;



Como vemos , al iniciar cada grupo nos muestra 0 ya que se estableció en el PARTITION BY DEPTNO.


Espero les sea útil como a mi estas funciones.

lunes, 7 de mayo de 2018

Clausula WITH Oracle 12C

Saludos,

La clausula WITH nos ayuda a simplificar los SQL complejos "SQL Complejos con WITH", en la versión 12C se incluye el poder incluir funciones y procedimiento dentro de la consulta cuya definición sea en linea durante la ejecución del SQL.

Exclusiones WITH
No pueden ser creados dentro de programación  PL/SQL o bloque anonimos.

Clausula WITH Function
Clausula para la definición de una función con el comando with

Declaracion.
WITH
  FUNCTION with_function(p_valor IN NUMBER) RETURN NUMBER IS
  BEGIN
    RETURN p_valor;
  END;
SELECT with_function(level)
FROM   dual
WHERE  rownum = 1
/​

WITH_FUNCTION(LEVEL)
--------------------
                   0
1 row selected.

En este ejemplo vemos que declaramos la función with_function dentro de la clausula WITH y lo invocamos en el SQL.

Clausula WITH Procedure
Dentro del mismo With podemos realizar declaraciones de procedimiento que pueden o no estar siendo invocados.

Declaracion.
WITH
  --Procedimiento
  PROCEDURE with_procedure(p_valor IN NUMBER) IS
  BEGIN
    DBMS_OUTPUT.put_line('p_valor=' || p_valor);
  END;
  --Funcion
  FUNCTION with_function(p_valor IN NUMBER) RETURN NUMBER IS
  BEGIN
    with_procedure(p_valor);
    RETURN p_valor;
  END;
SELECT with_function(level)
FROM   dual
WHERE  rownum = 1
/

WITH_FUNCTION(LEVEL)
--------------------
                   0

1 row selected.

DBMS_OUTPUT

p_valor=0



Como se ve en este ejemplo tenemos una función with_function y un procedimiento with_procedure. La funcion with_function llama al procedimiento with_procdure.


Clausula WITH SQL, Procedure y Function
Vamos a realizar algo mas complejo, vamos introducir un WITH SQL llamado with_sql el cual lo invocaremos desde el SQL principal.

Declaracion.
WITH
  --Procedimiento
  PROCEDURE with_procedure(p_valor IN NUMBER) IS
  BEGIN
    DBMS_OUTPUT.put_line('p_valor=' || p_valor);
  END;
  --Funcion
  FUNCTION with_function(p_valor IN NUMBER) RETURN NUMBER IS
  BEGIN
    with_procedure(p_valor);
    RETURN p_valor +1;
  END;
  --SQL
  with_sql as
  (
    select rownum fila, sysdate+rownum  fecha  from dual connect by level <=5
  )
SELECT a.fecha, a.fila,with_function(a.fila) resultado
FROM   with_sql  a
/


FECHA          FILA  RESULTADO
-------- ---------- ----------
08/05/18          1          2
09/05/18          2          3
10/05/18          3          4
11/05/18          4          5
12/05/18          5          6

5 rows selected.
​DBMS_OUTPUT
p_valor=1
p_valor=2
p_valor=3
p_valor=4
p_valor=5


Que es mejor, crear un PL/SQL o Definir en linea con WITH?
Todo esto dependerá la reutilización del código o su funcionalidad, por ejemplo si vamos a crear una funcion que solo va a funcionar en en un SQL específico no hay necesidad de crear un objeto Function y llenarnos de objetos. En este caso podemos usar la definición de la función dentro del WITH.

En cuestión de rendimiento la definición en linea tiene mejor desempeño. Veamos.

Para este ejemplo crearemos primero un función normal_function para poder hacer el comparativo con la with_function.

Creación de funcion PLSQL.
--Creacion de funcion PLSQL para probar
CREATE OR REPLACE FUNCTION normal_function(p_valor IN NUMBER) RETURN NUMBER IS
BEGIN
  RETURN p_valor+1;
END;
/​

Script para comprar el rendimiento del WITH_FUNCTION VS NORMAL_FUNCTION. Para ello tomaremos los tiempos de procesador para comparar el tiempo de ejecución.

Comparativo WITH_FUNCTION VS NORMAL_FUNCTION.
DECLARE
  l_time    PLS_INTEGER;
  l_cpu     PLS_INTEGER;
 
  l_sql     VARCHAR2(32767);
  l_cursor  SYS_REFCURSOR;
 
  TYPE t_tab IS TABLE OF NUMBER;
  l_tab t_tab;
BEGIN
  l_time := DBMS_UTILITY.get_time;
  l_cpu  := DBMS_UTILITY.get_cpu_time;

  l_sql := 'WITH
              FUNCTION with_function(p_valor IN NUMBER) RETURN NUMBER IS
              BEGIN
                RETURN p_valor;
              END;
            SELECT with_function(level)
            FROM   dual connect by level <1000000';
           
  OPEN l_cursor FOR l_sql;
  FETCH l_cursor
  BULK COLLECT INTO l_tab;
  CLOSE l_cursor;
 
  DBMS_OUTPUT.put_line('WITH_FUNCTION  : ' ||
                       'Time=' || TO_CHAR(DBMS_UTILITY.get_time - l_time) || ' hsecs ' ||
                       'CPU Time=' || (DBMS_UTILITY.get_cpu_time - l_cpu) || ' hsecs ');

  l_time := DBMS_UTILITY.get_time;
  l_cpu  := DBMS_UTILITY.get_cpu_time;

  l_sql := 'SELECT normal_function(level)
            FROM   dual connect by level<1000000 ';
           
  OPEN l_cursor FOR l_sql;
  FETCH l_cursor
  BULK COLLECT INTO l_tab;
  CLOSE l_cursor;
 
  DBMS_OUTPUT.put_line('NORMAL_FUNCTION: ' ||
                       'Time=' || TO_CHAR(DBMS_UTILITY.get_time - l_time) || ' hsecs ' ||
                       'CPU Time=' || (DBMS_UTILITY.get_cpu_time - l_cpu) || ' hsecs ');

END;

/
WITH_FUNCTION  : Time=129 hsecs CPU Time=108 hsecs
NORMAL_FUNCTION: Time=212 hsecs CPU Time=210 hsecs

Vemos que WITH_FUNCTION tomo casi la mitad del tiempo que NORMAL_FUNCTION.

jueves, 3 de mayo de 2018

Oracle Database Recovery Advisor (DRA)

DRA o Database Recovery Advisor es una utilidad del RMAN que nos hace mas fácil y acorta el tiempo de recuperación ante desastres ante daños de bloque de datos o archivos de datos de la base.

Database Recovery Advisor

Database Recovery Advisor (DRA) es un asistente para realizar recuperaciones en la base de datos de manera automática. Automáticamente diagnostica corrupción o perdida de archivos de base de datos en disco, el determina las opciones de recuperación y realiza la recuperación según la petición del usuario.

Esto es una gran ayuda para reducir los tiempos de de recuperacion MTTR (Mean Time To Recover).

La utilidad viene incluida en el RMAN, por ello para que su funcionamiento sea optimo se debe tener aplicado una politica de respaldo con RMAN, en caso de no tener no nos servirá de mucho del DRA.

Componentes mas importantes del DRA

  • LIST FAILURE
  • ADVISE FAILURE
  • CHANGE FAILURE
  • VALIDATE


A continuación las opciones mas importantes del  DRA

LIST FAILURE
Desde el RMAN con esta opcion determinamos de una forma facil el fallo en la base de datos de categoría CRITICAL o HIGH.



ADVISE FAILURE
El comando ADVISE FAILURE, como su nombre lo indica, proporciona consejos de reparación para fallas enumeradas por el comando LIST FAILURE, así como el cierre de todas las fallas abiertas que ya están reparada

REPAIR FAILURE
El comando REPAIR FAILURE aplica los scripts de reparación producidos por el comando ADVISE FAILURE. El uso de la opción PREVIEW enumera los contenidos del script de reparación sin aplicarlo.

CHANGE FAILURE
El comando CHANGE FAILURE le permite cambiar la prioridad de una falla o cerrar una falla abierta. Es posible que desee cambiar la prioridad de una falla si no representa un problema para usted. Por ejemplo, una falla asociada con un espacio de tabla que usted conoce por más tiempo puede aparecer como una prioridad alta, cuando en realidad no tiene ningún efecto en el funcionamiento normal de su sistema

VALIDATE
El comando VALIDAR inicia las comprobaciones de integridad de los datos, el registro físico y, opcionalmente, las corrupciones de bloques lógicas de los archivos de la base de datos y las copias de seguridad en la vista V$DATABASE_BLOCK_CORRUPTION y el Repositorio de diagnóstico automático como uno o más fallos.


EJEMPLO
Para este ejemplo vamos hacer una maldad a la base de datos, como? vamos a realizar un borrado de unos de los datafile del tablespace USER.

Para esto debemos

  1. Generar un respaldo con el RMAN
  2. Eliminar el datafile
  3. Listar la falla, 
  4. Presentar las recomendaciones
  5. Aplicar la solución.

Generar un respaldo con el RMAN

Requisito que la base de datos este en modo archivelog.

Verificar el modo archivelog de la base.
oracle@srvdb01 ~]$ . oraenv
ORACLE_SID = [oracle] ? orcl
The Oracle base has been set to /u01/app/oracle


[oracle@srvdb01 ~]$ sqlplus / as sysdba
SQL> select log_mode from v$database;
LOG_MODE
------------
NOARCHIVELOG​
//Si no esta en modo archivelog se lo configura

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup mount;
ORACLE instance started.
Total System Global Area  968884224 bytes
Fixed Size     2931424 bytes
Variable Size   352322848 bytes
Database Buffers   608174080 bytes
Redo Buffers     5455872 bytes
Database mounted.

SQL> alter database archivelog;
Database altered.

SQL> alter database open;
Database altered.
​​

Respaldo con el RMAN

[oracle@srvdb01 ~]$ rman target /
Recovery Manager: Release 12.1.0.2.0 - Production on Wed May 2 09:50:11 2018
Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.
connected to target database: ORCL (DBID=1500358275)


RMAN> backup database;

Starting backup at 02-MAY-18
using channel ORA_DISK_1
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00005 name=+FRA/ORCL/DATAFILE/example.269.972577567
input datafile file number=00001 name=+FRA/ORCL/DATAFILE/system.257.972577339
input datafile file number=00003 name=+FRA/ORCL/DATAFILE/sysaux.256.972577245
input datafile file number=00004 name=+FRA/ORCL/DATAFILE/undotbs1.259.972577407
input datafile file number=00006 name=+FRA/ORCL/DATAFILE/users.258.972577405
channel ORA_DISK_1: starting piece 1 at 02-MAY-18
channel ORA_DISK_1: finished piece 1 at 02-MAY-18
piece handle=+FRA/ORCL/BACKUPSET/2018_05_02/nnndf0_tag20180502t180015_0.274.975088819 tag=TAG20180502T180015 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:03:45
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
including current control file in backup set
including current SPFILE in backup set
channel ORA_DISK_1: starting piece 1 at 02-MAY-18
channel ORA_DISK_1: finished piece 1 at 02-MAY-18
piece handle=+FRA/ORCL/BACKUPSET/2018_05_02/ncsnf0_tag20180502t180015_0.275.975089045 tag=TAG20180502T180015 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 02-MAY-18
​​


Eliminar el datafile
Se tiene que bajar la instancia de base de datos para la eliminación del datafile
Bajar la instancia ORCL.
[oracle@srvdb01 ~]$ . oraenv
ORACLE_SID = [orcl] ? orcl
The Oracle base remains unchanged with value /u01/app/oracle


[oracle@srvdb01 ~]$ sqlplus / as sysdba
SQL*Plus: Release 12.1.0.2.0 Production on Thu May 3 15:31:32 2018
Copyright (c) 1982, 2014, Oracle.  All rights reserved.​

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.​

En mi caso tengo una base de datos ASM, por lo que tengo que eliminar el datafile en el almacenamiento ASM y esto lo realizare desde el ASMCMD.
Eliminar el datafile desde el ASMCMD.
[oracle@srvdb01 ~]$ . oraenv
ORACLE_SID = [oracle] ? +ASM
The Oracle base has been set to /u01/app/oracle


[oracle@srvdb01 ~]$ asmcmd
ASMCMD> cd +FRA/ORCL/DATAFILE
ASMCMD> ls
EXAMPLE.269.972577567
SYSAUX.256.972577245
SYSTEM.257.972577339
UNDOTBS1.259.972577407
USERS.258.972577405


ASMCMD> rm USERS.258.972577405​

Intentamos de iniciar la base de datos ORCL
Iniciamos la base de datos.
SQL> startup
ORACLE instance started.
Total System Global Area  968884224 bytes
Fixed Size     2931424 bytes
Variable Size   352322848 bytes
Database Buffers   608174080 bytes
Redo Buffers     5455872 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 6 - see DBWR trace file
ORA-01110: data file 6: '+FRA/ORCL/DATAFILE/users.258.972577405'

Como vemos nos genero un error ORA-01110, que esta relacionado con el archivo que borramos. La base de datos no se pudo abrir.

Listar la falla 
Aqui vamos a ver que nos disnostica como problema el DRA.
Listar la falla RMAN DRA.
RMAN> LIST FAILURE;
Database Role: PRIMARY
List of Database Failures
=========================
Failure ID Priority Status    Time Detected Summary
---------- -------- --------- ------------- -------
42         HIGH     OPEN      03-MAY-18     One or more non-system datafiles are missing​


Presentar las recomendaciones
Vamos a ver las recomendaciones del DRA para la solución del problema, están pueden ser varias
Listar recomendaciones RMAN DRA.
RMAN> ADVISE FAILURE;
Database Role: PRIMARY
List of Database Failures
=========================
Failure ID Priority Status    Time Detected Summary
---------- -------- --------- ------------- -------
42         HIGH     OPEN      03-MAY-18     One or more non-system datafiles are missing
analyzing automatic repair options; this may take some time
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=27 device type=DISK
analyzing automatic repair options complete
Mandatory Manual Actions
========================
no manual actions available
Optional Manual Actions
=======================
1. If file +FRA/ORCL/DATAFILE/users.258.972577405 was unintentionally renamed or moved, restore it
Automated Repair Options
========================
Option Repair Description
------ ------------------
1      Restore and recover datafile 6
  Strategy: The repair includes complete media recovery with no data loss
  Repair script: /u01/app/oracle/diag/rdbms/orcl/orcl/hm/reco_1926445353.hm​


Aplicar la solución
Antes de aplicar la solución podemos ver el script que se aplicara antes de aplicar la solución.

Previsualización de la recomendacion REPAIR FAILURE PREVIEW.
RMAN> REPAIR FAILURE PREVIEW;
Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/orcl/orcl/hm/reco_1926445353.hm

contents of repair script:
   
# restore and recover datafile
   restore ( datafile 6 );
   recover datafile 6;
   sql 'alter database datafile 6 online';

Ahora si, aplicamos la solución
Aplicamos la solucion.
RMAN> REPAIR FAILURE;
Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/orcl/orcl/hm/reco_1926445353.hm

contents of repair script:
   # restore and recover datafile
   restore ( datafile 6 );
   recover datafile 6;
   sql 'alter database datafile 6 online';

Do you really want to execute the above repair (enter YES or NO)? YES
executing repair script

Starting restore at 03-MAY-18
using channel ORA_DISK_1

channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00006 to +FRA/ORCL/DATAFILE/users.258.972577405
channel ORA_DISK_1: reading from backup piece +FRA/ORCL/BACKUPSET/2018_05_02/nnndf0_tag20180502t180015_0.274.975088819
channel ORA_DISK_1: piece handle=+FRA/ORCL/BACKUPSET/2018_05_02/nnndf0_tag20180502t180015_0.274.975088819 tag=TAG20180502T180015
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:00:02
Finished restore at 03-MAY-18

Starting recover at 03-MAY-18
using channel ORA_DISK_1

starting media recovery
media recovery complete, elapsed time: 00:00:03

Finished recover at 03-MAY-18
sql statement: alter database datafile 6 online
repair failure complete

Do you want to open the database (enter YES or NO)? yes
database opened

Listo, como se ve en las ultimas lineas el advisor finaliza la tarea y pregunta si se desea dejar abierta la base de datos con unos pocos pasos haciendo mas rápido el disgnostico del error como su solución.

Como ven la vida del DBA es mas facil!!,