1. Documentación en Tahiti -> Masters Book List -> Backup and Recovery User’s Guide -> 17 Performing Complete Database Recovery
Documentación en Tahiti -> Masters Book List -> Backup and Recovery User’s Guide -> 30 Performing User-Managed Recovery: Advanced Scenarios
2. Este es un objetivo crucial y no me refiero sólo al examen. Vamos a practicar distintos escenarios «desastre» en los que hemos perdido uno o varios archivos y tenemos que tener muy claro como poder recuperar la BD en todos los casos. Algún caso «extremo» conllevará perdida de información, pero también tenemos que saber como levantar la BD y dejarla operativa.
Esta es la lista de escenarios que vamos a practicar:
· Perdida de DATAFILE de SYSTEM
· Perdida de DATAFILE NO de SYSTEM
· Perdida de DATAFILE sin Backup
· Perdida de UN CONTROLFILE
· Perdida de TODOS los CONTROLFILE
· Perdida de ARCHIVELOG y REDOLOG
· Perdida de SPFILE, CONTROLFILE, DATAFILES y REDOLOGS
3. Comenzamos con el primer escenario. Vamos a borrar el DATAFILE 1, que pertenece al tablespace de SYSTEM y veamos como hay que realizar la recuperación. Antes de todo, aseguraros de que tenéis un Backup válido de la BD.
# Borramos el DATAFILE 1 rm /u01/app/oracle/oradata/OCM/system01.dbf
Aunque la BD se caerá antes o después, nosotros forzamos un ABORT para agilizar la operación.
-- Apagamos la BD SHUTDOWN ABORT STARTUP MOUNT
# Nos conectamos con rman a la BD y el catálogo</span> <pre>rman target sys@ocm catalog rman/rman@oem #Restauramos y recuperamos el DATAFILE RESTORE DATAFILE 1; RECOVER DATAFILE 1; sql 'ALTER DATABASE OPEN';
4. ¿Qué sucede si perdemos un DATAFILE que no pertenece al tablespace SYSTEM? Muchisimo más fácil. Lo ponemos OFFLINE -> RESTORE DATAFILE -> RECOVER DATAFILE -> ONLINE. Pero en vez de hacerlo de la forma tradicional, vamos a usar una nueva funcionalidad que se llama Data Recovery Advisor (DRA) de la versión 11g. Esta realiza un diagnóstico del problema que está sucediendo y nos genera recomendaciones para solucionarlo.
# Borramos el DATAFILE del TABLESPACE USERS rm /u01/app/oracle/oradata/OCM/users01.dbf
-- Forzamos el fallo intento escribir en el TBS CREATE TABLE TEST (C1 NUMBER) TABLESPACE USERS;
# Nos conectamos con rman a la BD y el catálogo rman target sys@ocm catalog rman/rman@oem # Los comandos específicos de DRA se ejecutan dentro de RMAN # Listamos el problema que hay en BD LIST FAILURE; # Analizamos el fallo para que DRA nos genere un script de correciones ADVISE FAILURE; # Vemos el contenido del script de reparación REPAIR FAILURE PREVIEW; # Ejecutamos el script REPAIR FAILURE;
5. Una posible situación se puede dar cuando tenemos que recuperar un fichero en una ubicación distint a la original, porque se ha perdido (sí, esto sucede, para nuestra desgracia). Aunque también es fácil. Adjunto el script completo para realizarlo con el mismo DATAFILE del ejercicio anterior.
# Borramos el DATAFILE del TABLESPACE USERS rm /u01/app/oracle/oradata/OCM/users01.dbf
-- Forzamos el fallo intento escribir en el TBS CREATE TABLE TEST (C1 NUMBER) TABLESPACE USERS;
RUN { sql 'ALTER DATABASE DATAFILE 4 OFFLINE'; SET NEWNAME FOR DATAFILE 4 TO '/u02/app/oracle/oradata/OCM/users01.dbf'; RESTORE DATAFILE 4; SWITCH DATAFILE 4; RECOVER DATAFILE 4; sql 'ALTER DATABASE DATAFILE 4 ONLINE'; }
6. Si perdemos un DATAFILE y no tenemos Backup, aún podemos recuperar el DATAFILE. Las condiciones que debemos cumplir es que debemos tener todos los ARCHIVELOG desde que se creó dicho DATAFILE y además el nombre del DATAFILE está incluido en el CONTROLFILE. Podemos usar las técnicas anteriores, pero también tenemos esta posibilidad.
-- Creamos un TABLESPACE de prueba con una tabla de ejemplo CREATE TABLESPACE TEST DATAFILE '/u01/app/oracle/oradata/OCM/test01.dbf' size 100M; CREATE TABLE TEST_TABLE TABLESPACE TEST AS SELECT * FROM HR.EMPLOYEES;
# Borramos el DATAFILE rm /u01/app/oracle/oradata/OCM/test01.dbf
-- Recuperamos el DATAFILE ALTER DATABASE DATAFILE 6 OFFLINE; -- Creamos un DATAFILE con las mismas características que el DATAFILE perdido -- Podemos usar el mismo nombre para recuperar en la ubicación original o una distinta ALTER DATABASE CREATE DATAFILE '/u01/app/oracle/oradata/OCM/test01.dbf' AS '/u02/app/oracle/oradata/OCM/test01.dbf'; RECOVER DATAFILE 6; ALTER DATABASE DATAFILE 6 ONLINE; -- Comprobamos que no hemos perdido datos SELECT COUNT(*) FROM TEST_TABLE; -- Limpiamos el entorno DROP TABLESPACE TEST INCLUDING CONTENTS AND DATAFILES; ALTER DATABASE CREATE DATAFILE '/u01/app/oracle/oradata/OCM/test01.dbf' AS '/u01/app/oracle/oradata/OCM/test01.dbf';
7. El siguiente escenario que quiero demostrar es la perdida de un CONTROLFILE. El procedimiento de recuperación consiste en copiar uno de los CONTROLFILE que tenemos en la máquina a la ubicación del que hemos perdido, y luego levantar la instancia. Ojo! Siempre hay que tener cuidado de no sobrescribir ningun CONTROLFILE, por si acaso. Antes de sobreescribir cualquier, lo copiamos o renombramos.
# Borramos un CONTROLFILE rm /u01/app/oracle/oradata/OCM/control01.ctl
-- Cerramos la BD (si es que no se ha caido) SHUTDOWN ABORT
# Copiamos el CONTROLFILE "vivo" en la ubicación del que hemos borrado cp -p /u01/app/oracle/fast_recovery_area/OCM/control02.ctl /u01/app/oracle/oradata/OCM/control01.ctl
-- Levantamos la BD STARTUP
8. Complicamos el ejercicio anterior, borrando todos los CONTROLFILE de la máquina.
# Borramos los dos CONTROLFILE que tenemos de la BD de OCM rm /u01/app/oracle/oradata/OCM/control01.ctl rm /u01/app/oracle/fast_recovery_area/OCM/control02.ctl
-- Cerramos la BD (si es que no se ha caido) SHUTDOWN ABORT
# Ejecutamos el siguiente script desde RMAN # Estos comandos se pueden ejecutando dentro de un bloque RUN, pero prefiero tener mayor control STARTUP NOMOUNT; RESTORE CONTROLFILE FROM AUTOBACKUP; sql 'ALTER DATABASE MOUNT'; RECOVER DATABASE; sql 'ALTER DATABASE OPEN RESETLOGS'; # Guardamos un BACKUP (IMPORTANTÍSIMO) BACKUP AS COMPRESSED BACKUPSET DATABASE PLUS ARCHIVELOG;
9. Ahora supongo que hemos perdido los REDOLOG (todos) y los ARCHIVELOG. Esto significa que tenemos que recuperar la BD desde el último backup completo y luego aplicar todos los archivelogs que hayamos salvaguardado.
-- Lo primero es poner la BD en estado MOUNT SHUTDOWN IMMEDIATE STARTUP MOUNT -- Obtenemos el último ARCHIVELOG aplicado para obtener la última secuencia (Ej) -- THREAD# RESETLOGS_CHANGE# ARC SEQUENCE# COMPLETIO --- --------- ----------------- --- ---------- --------- -- 1 3012881 YES 2 07-JUN-13 SELECT THREAD#, RESETLOGS_CHANGE#, ARCHIVED, SEQUENCE#, COMPLETION_TIME FROM V$ARCHIVED_LOG WHERE ARCHIVED='YES' AND COMPLETION_TIME = (SELECT MAX(COMPLETION_TIME) FROM V$ARCHIVED_LOG WHERE ARCHIVED='YES');
# Dentro de RMAN, recuperamos la BD hasta el último ARCHIVELOG # Si os fijáis, para que la BD recuperara hasta la SEQUENCE n (2), tenemos que indicar n+1 (3) RESTORE DATABASE; RECOVER DATABASE UNTIL SEQUENCE 3 THREAD 1; sql 'ALTER DATABASE OPEN RESETLOGS'; # Guardamos un BACKUP (IMPORTANTÍSIMO) BACKUP AS COMPRESSED BACKUPSET DATABASE PLUS ARCHIVELOG;
10. Entrenaremos ahora la perdida de SPFILE, CONTROLFILE, DATAFILES y REDOLOGS. Tenemos que recuperar el SPFILE/CONTROLFILE del AUTOBACKUP. Luego recuperaremos los DATAFILES y todos los ARCHIVELOGS que tengamos almacenados. Por último levantaremos la BD con RESETLOGS, ya que es una recuperación INCOMPLETA y la información que contiene no nos sirve.
# Borramos los ficheros rm /u01/app/oracle/oradata/OCM/system01.dbf rm /u01/app/oracle/oradata/OCM/sysaux01.dbf rm /u01/app/oracle/oradata/OCM/undotbs01.dbf rm /u02/app/oracle/oradata/OCM/users01.dbf rm /u02/app/oracle/oradata/OCM/system02.dbf rm /u01/app/oracle/oradata/OCM/temp01.dbf rm /u01/app/oracle/oradata/OCM/control01.ctl rm /u01/app/oracle/fast_recovery_area/OCM/control02.ctl rm /u01/app/oracle/product/11.2.0/dbhome_1/dbs/spfileOCM.ora rm /u01/app/oracle/oradata/OCM/redo101.log rm /u01/app/oracle/oradata/OCM/redo201.log rm /u01/app/oracle/oradata/OCM/redo301.log rm /u02/app/oracle/oradata/OCM/redo102.log rm /u02/app/oracle/oradata/OCM/redo202.log rm /u02/app/oracle/oradata/OCM/redo302.log # Tiramos la BD SHUTDOWN ABORT # Nos conectamos con RMAN rman target sys@ocm catalog rman/rman@oem # Fijamos el DBID de la BD # Lo podemos obtener de los logs previos de RMAN o consultado el catálogo # Ej: connected to target database: OCM (DBID=2196200734) # Ej2: SELECT DB_ID FROM DB WHERE DB_KEY = (SELECT DB_KEY FROM DBINC # WHERE DB_NAME='OCM' AND DBINC_STATUS='CURRENT'); SET DBID 2196200734
-- Levantamos la instancia en modo NOMOUNT STARTUP NOMOUNT
El primero paso es recuperar el SPFILE del AUTOBACKUP. Pero primero tenemos que configurar la FRA para que RMAN pueda encontrar el AUTOBACKUP sin problemas.
-- Configuramos los parámetros de la FRA ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE=4G; ALTER SYSTEM SET DB_RECOVERY_FILE_DEST='/u01/app/oracle/fast_recovery_area';
# Recuperamos el SPFILE, reinciamos la instancia y restauramos la BD RESTORE SPFILE FROM AUTOBACKUP; SHUTDOWN IMMEDIATE; STARTUP NOMOUNT; RESTORE CONTROLFILE FROM AUTOBACKUP; ALTER DATABASE MOUNT; RESTORE DATABASE
-- Obtenemos el último ARCHIVELOG DISPONIBLE SELECT THREAD#, RESETLOGS_CHANGE#, ARCHIVED, SEQUENCE#, COMPLETION_TIME FROM V$ARCHIVED_LOG WHERE ARCHIVED='YES' AND COMPLETION_TIME = (SELECT MAX(COMPLETION_TIME) FROM V$ARCHIVED_LOG WHERE ARCHIVED='YES');
# Recuperamos hasta el último ARCHIVELOG (n+1) y abrimos con RESETLOGS RECOVER DATABASE UNTIL SEQUENCE 3 THREAD 1; sql 'ALTER DATABASE OPEN RESETLOGS'; # Realizamos otro backup BACKUP AS COMPRESSED BACKUPSET DATABASE PLUS ARCHIVELOG;
11. Simulamos la perdida del TABLESPACE temporal.
# Borramos el DATAFILE del tablespace temporal rm /u01/app/oracle/oradata/OCM/temp01.dbf
-- Creamos un TABLESPACE temporal y lo asignamos por defecto a la BD CREATE TEMPORARY TABLESPACE TEMP2 TEMPFILE '/u01/app/oracle/oradata/OCM/temp201.dbf' size 20M; ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMP2; -- Recreamos el tablespace TEMP y lo asignamos por defecto a la BD DROP TABLESPACE TEMP; CREATE TEMPORARY TABLESPACE TEMP TEMPFILE '/u01/app/oracle/oradata/OCM/temp01.dbf' size 20M; ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMP; -- Borramos el tablespace TEMP2 que hemos utilizado -- Si no nos deja, tenemos que eliminar las sesiones que lo estén utilizando (la tuya propia, por ej.) -- SELECT USERNAME, SESSION_NUM, SESSION_ADDR FROM V$SORT_USAGE; DROP TABLESPACE TEMP2 INCLUDING CONTENTS AND DATAFILES;
12. Es posible, que infrecuente, que se produzca una corrupción de bloques en uno o varios ficheros de la BD. Si tenemos un backup válido de la BD y la tenemos en modo ARCHIVELOG no debería ser un problema. Vamos a simular una corrupción en un datafile de prueba y veremos cómo solucionarlo.
-- Creamos un TBS de prueba CREATE TABLESPACE BC DATAFILE '/u01/app/oracle/oradata/OCM/bc01.dbf' SIZE 20M; -- Creamos una tabla de ejemplo en dicho TBS CREATE TABLE TEST_BC TABLESPACE BC AS SELECT * FROM DBA_OBJECTS; -- Localizamos el Datafile (FILE_NO) y un bloque donde se almacena dicha tabla -- En mi ejemplo obtengo esta salida: -- FILE_NO BLOCK_NO -- ---------- ---------- -- 5 131 SELECT DISTINCT MIN(DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) as FILE_NO, MIN(DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)) as BLOCK_NO FROM TEST_BC; -- Limpiamos la caché (así forzamos que se muestre la corrupción rapidamente) ALTER SYSTEM FLUSH BUFFER_CACHE;
Ahora debemos corromper dicho bloque con el comando ‘dd’ de Linux.
# Ejecutamos el comando dd dos veces para corromper el bloque que hemos localizado y el siguiente # Lo importante es indicar el desplazamiento (SEEK = BLOCK_NO), en nuestro ejemplo seek=131 dd of=/u01/app/oracle/oradata/OCM/bc01.dbf bs=8192 conv=notrunc seek=131 << EOF OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm EOF dd of=/u01/app/oracle/oradata/OCM/bc01.dbf bs=8192 conv=notrunc seek=132 << EOF OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm OCM ocm EOF
-- Forzamos la detección del bloque corrupto -- Deben aparecer los errores ORA_01578 y ORA-01110 SELECT * FROM TEST_BC; -- Podemos ver como se ha poblado la tabla V$DATABASE_BLOCK_CORRUPTION SELECT * FROM V$DATABASE_BLOCK_CORRUPTION;
Vamos a utilizar DRA (Data Recovery Advisor) para recuperar estos bloques corruptos. Como ya lo hemos usado en ejercicios anteriores, vamos a hacerlo rapidamente.
# Nos conectamos con RMAN, listamos el fallo y obtenemos la recomendación de DRA rman target / catalog rman/rman@OEM LIST FAILURE; ADVISE FAILURE; # En otra sesión, vemos el contenido del fichero que se va a ejecutar para recuperar los bloques # El contenido del script es el siguiente: # # block media recovery for multiple blocks # recover datafile 5 block 131 to 132; cat /u01/app/oracle/diag/rdbms/ocm/OCM/hm/reco_3702026499.hm # Lanzamos con RMAN el script de recuperación REPAIR FAILURE;
-- Por último vamos a consultar de nuevo la tabla para ver si se ha corregido el problema. SELECT * FROM TEST_BC; -- Limpiamos el entorno DROP TABLESPACE BC INCLUDING CONTENTS AND DATAFILES;