miércoles, 23 de julio de 2008

Uso de RMAN para Respaldos

Recuerdo a mi primer Jefe cuando empecé a desempeñar mi trabajo como DBA, lo que más me recalcó fue mi responsabilidad no sólo de poder realizar backups, sino de poder restaurar la información de mis backups. Esta responsabilidad es la que me gusta transmitir a todos los DBAs con los cuáles he interactuado.

De nada sirve tener un backup si no vas a poder recuperar la información.

A menudo me preguntan sobre las formas de respaldos de bases de datos oracle, y siempre respondo que lo mejor es el uso de RMAN. ¿Qué tan complejo puede ser RMAN?, la realidad es que ya configurado es muy sencillo, o en su forma más simple, sacar un respaldo es cuestión de un comando en 2 palabras:


C:\Documents and Settings\Hugo\Escritorio>rman target /

Recovery Manager : Release 10.2.0.3.0 - Production on Mié Jul 23 13:21:30 2008

Copyright (c) 1982, 2005, Oracle. All rights reserved.

conectado a la base de datos destino: ORCL (DBID=524232147)

RMAN> backup database;


¿Y el restore?



C:\Documents and Settings\Hugo\Escritorio>rman target /

Recovery Manager : Release 10.2.0.3.0 - Production on Mié Jul 23 13:22:35 2008

Copyright (c) 1982, 2005, Oracle. All rights reserved.

conectado a la base de datos destino: ORCL (DBID=524232147)

RMAN> shutdown abort;

RMAN> startup mount;

RMAN> restore database;

RMAN> recover database;

RMAN> alter database open;



Claro es sencillo porque la base de datos está en modo archive, a pesar que no estoy usando un catálogo de RMAN (que sería lo más recomendable), el restore es muy sencillo.

La realidad es que no siempre tenemos este esquema "utópico" a nivel base de datos. En alguna ocasión me tocó clonar la base de datos de un cliente con RMAN, tenían la base de datos en modo Archive, hicieron un hotbackup y al final del día, la información que se restauró sobre la instancia de desarrollo estaba corrupta.

Lo que sucedió fue lo siguiente:

El cliente estaba realizando algunas cargas de información sobre sus tablas.

El "DBA" para realizar las cargas más rápidas, decidió usar el método de "Direct Load" (que me pareció muy buena opción), sobre la tabla alterada con nologging (que me pareció una pésima opción).

A la hora de realizar el respaldo, e incluso los archives, no se tenía rastro de los insert sobre la tabla; se tenían rastros de los incrementos de extents y del movimiento del HWM. Para ejemplificar lo sucedido podemos hacer lo siguiente con dos sesiones:

Primera sesión en SQL*Plus:


SQL> alter table prueba nologging;

Tabla modificada.

SQL> begin
2 for a in 1..100
3 loop
4 insert /*+APPEND*/ into prueba (select substr(object_name,1,3),CREATED,substr(owner,1,3)from dba_objects);
5 commit;
6 dbms_lock.sleep(2);
7 end loop;
8 end;
9 /



y en una sesión de RMAN


C:\Documents and Settings\Hugo\Escritorio>rman target /

Recovery Manager : Release 10.2.0.3.0 - Production on Mié Jul 23 15:58:03 2008

Copyright (c) 1982, 2005, Oracle. All rights reserved.

conectado a la base de datos destino: HECG (DBID=524232147)

RMAN> backup database plus archivelog;


Con el comando plus archivelog, nos aseguramos de que todos los archives necesarios para restaurar este backup se incluyan, e incluso realiza un switch log al finalizar y respalda los archives nuevamente.

La sesión de SQL*Plus termina, el backup termina y empezamos con el restore:

Ahora, pensando en que tuviéramos una falla en ese momento y queremos recuperar, podemos empezar un restore a cierta fecha (que es cuando el respaldo terminó):


RMAN> shutdown abort;

RMAN> startup mount

instancia Oracle iniciada

Total del Área Global del Sistema 289406976 bytes

Fixed Size 1290184 bytes
Variable Size 272629816 bytes
Database Buffers 8388608 bytes
Redo Buffers 7098368 bytes

base de datos montada

RMAN> run {
2> set until time "to_date('23-07-2008 16:01:12','dd-mm-yyyy hh24:mi:ss')";
3> restore database;
4> recover database;
5> }

ejecutando el comando: SET until clause

Iniciando restore en 21-JUL-08
canal asignado: ORA_DISK_1
canal ORA_DISK_1: sid=156 devtype=DISK

canal ORA_DISK_1: iniciando restauraci+¦n del juego de copias de seguridad de archivos de datos
canal ORA_DISK_1: especificando archivo(s) de datos para restaurar del juego de copias de seguridad
restaurando el archivo de datos 00001 en C:\ORACLE\PRODUCT\ORADATA\ORCL\SYSTEM01.DBF
restaurando el archivo de datos 00002 en C:\ORACLE\PRODUCT\ORADATA\ORCL\UNDOTBS01.DBF
restaurando el archivo de datos 00003 en C:\ORACLE\PRODUCT\ORADATA\ORCL\SYSAUX01.DBF
restaurando el archivo de datos 00004 en C:\ORACLE\PRODUCT\ORADATA\ORCL\USERS01.DBF
restaurando el archivo de datos 00005 en C:\ORACLE\PRODUCT\ORADATA\ORCL\EXAMPLE01.DBF
restaurando el archivo de datos 00006 en C:\CRYPTO\ORCL\DATAFILE\O1_MF_ORCL_42K6N37T_.DBF
restaurando el archivo de datos 00007 en C:\PRUEBA01.DBF
canal ORA_DISK_1: leyendo desde la parte de copia de seguridad C:\ORACLE\PRODUCT\FLASH_RECOVERY_AREA\ORCL\BACKUPSET\2008_07_21\O1_MF_NNNDF_TAG20080721T093726_4897S8PY_.BKP

RMAN> alter database open resetlogs;



Se debe de utilizar un resetlogs ya se usó una recuperación incompleta.

Ahora entramos a SQL*Plus y ejecutamos un sql contra la tabla prueba


SQL> select count(1) from prueba;
select count(1) from prueba
*
ERROR en línea 1:
ORA-01578: bloque de datos ORACLE corrupto (archivo número 4, bloque número 10251)
ORA-01110: archivo de datos 4: 'C:\ORACLE\PRODUCT\ORADATA\ORCL\USERS01.DBF'
ORA-26040: Se ha cargado el bloque de datos utilizando la opción NOLOGGING


La tabla queda en un estado inconsistente porque el diccionario de datos (que sí genera redo) registró el crecimiento de bloques en la tabla, pero el objeto como tal no.

Hay algunas formas de recuperar algo de información si es que los índices estaban en modo logging, pero creanme... estamos en el peor caso de recuperación.

Dado todo lo anterior, creo que sólo se me ocurre una posibilidad para evitar esto durante un backup. Y es uno de los comandos que se suelen usar en dataguard


RMAN> run {
2> sql "alter database force logging";
3> backup database include current controlfile plus archivelog;
4> sql "alter database no force logging";
5> }

Iniciando backup en 23-JUL-08
log actual archivado
usando el canal ORA_DISK_1
canal ORA_DISK_1: iniciando juego de copias de seguridad de archive log
canal ORA_DISK_1: especificando archive log(s) en el juego de copias de seguridad
thread de archive log de entrada=1 secuencia=1 recid=122 marca=660762972
thread de archive log de entrada=1 secuencia=2 recid=123 marca=660763141
thread de archive log de entrada=1 secuencia=3 recid=124 marca=660763187
canal ORA_DISK_1: iniciando parte 1 en 22-JUL-08
...
canal ORA_DISK_1: especificando archivo(s) de datos en el juego de copias de seguridad
incluyendo el archivo de control actual en el juego de copias de seguridad
manejador de parte=C:\ORACLE\PRODUCT\FLASH_RECOVERY_AREA\ORCL\BACKUPSET\2008_07_23\O1_MF_NCNNF_TAG20080723T172009_48DQF74D_.BKP etiqueta=TAG20080723T172009 comentario=NONE
canal ORA_DISK_1: juego de copias de seguridad terminado, tiempo transcurrido: 00:00:06
backup terminado en 23-JUL-08
thread de archive log de entrada=1 secuencia=4 recid=125 marca=660763348
thread de archive log de entrada=1 secuencia=5 recid=126 marca=660763352
backup terminado en 23-JUL-08


En este caso estoy incluyendo el controlfile para hacer una especie de recuperación de desastre (que fue lo que hice realmente como clonado). Al mismo tiempo lancé el insert sobre la tabla prueba a través del ciclo y con la tabla en nologging.

Ya que es una recuperación de desastre, simularemos la pérdida del controlfile, y para poder recuperarlo, necesitamos el DBID de nuestra base de datos (se puede obtener conectándonos a rman o desde v$database).

Hay que tener en cuenta el nombre del archivo que guarda el controlfile para poder extraerlo, así como las secuencias de archives que se tienen registradas en el bacjup para restaurar y recuperar.


RMAN> shutdown abort;

instancia Oracle cerrada

RMAN> startup nomount;

conectado a la base de datos destino (no iniciada)
instancia Oracle iniciada

Total del Área Global del Sistema 289406976 bytes

Fixed Size 1290184 bytes
Variable Size 226492472 bytes
Database Buffers 54525952 bytes
Redo Buffers 7098368 bytes

RMAN> SET DBID 524232147;

ejecutando el comando: SET DBID

RMAN> RUN
2> {
3> RESTORE CONTROLFILE FROM 'C:\ORACLE\PRODUCT\FLASH_RECOVERY_AREA\ORCL\BACKUPSET\2008_07_23\O1_MF_NCNNF_TAG20080723T172009_48DQF74D_.BKP
4> }

Iniciando restore en 22-JUL-08
canal asignado: ORA_DISK_1
canal ORA_DISK_1: sid=156 devtype=DISK

canal ORA_DISK_1: restaurando archivo de control
canal ORA_DISK_1: restauración terminada, tiempo transcurrido: 00:00:04
archivo de salida=C:\ORACLE\PRODUCT\ORADATA\ORCL\CONTROL01.CTL
archivo de salida=C:\ORACLE\PRODUCT\ORADATA\ORCL\CONTROL02.CTL
archivo de salida=C:\ORACLE\PRODUCT\ORADATA\ORCL\CONTROL03.CTL
restore terminado en 22-JUL-08

RMAN> alter database mount;

base de datos montada
canal liberado: ORA_DISK_1

RMAN> RESTORE DATABASE UNTIL SEQUENCE 5;

RMAN> RECOVER DATABASE UNTIL SEQUENCE 5;

RMAN> ALTER DATABASE OPEN RESETLOGS;



Y ahora podemos conectarnos a SQL*Plus


SQL> select count(1) from prueba;

COUNT(1)
----------
9813490


Este ejemplo es muy raro que se encuentre en un ambiente productivo, y más que poder lanzar los comandos sql de "alter database force logging", como DBAs debemos de analizar que nuestros objetos tengan activado el logging. Habrá quien diga que los índices pueden ir en nologging, pero les preguntaría... ¿Cuánto tiempo tardarían en recrear los índices que no tuvieran activado el logging?

En algún otro Post pondré los scripts que se pueden usar para extraer datos de índices correspondientes a una tabla perdida.

10 comentarios:

cinecomentado dijo...

y buena nota, ahora una consulta, tengo una base en PROD y hice un backup con RMAN que me genero los .rman, ahora lo que quiero hacer el hacer el restore de esta en el servidor de DESA, como lo haría con RMAN??? desde ya gracias!!!

Hugo E. Contreras Gamiño dijo...

Lo más sencillo es el comando duplicate, pondré un post pronto sobre este comando. Tambien puedes simular una recuperación de desastre, que sería exactamente igual a mi ejemplo (asumi4endo que respaldas a disco), pero copias TODOS tus archivos de un respaldo a las mismas rutas en tu servidor de desarrollo(si no pudes usar las mismas rutas, deberas de "catalogar" los archivos). Y ya en tu server de desarrollo empiezas con la base no montada, el comando "set dbid" y restore controlfile, etc...
o si bien tienes un controlfile que puedes copiar de prod, o que copiaste a la hora de tu respaldo, lo puedes poner en tu ambiente de desarrollo y montas la base de datos y le das "restore database" y "recover database", eso intentará llevar tu base a la sincronía del controlfile. Recuerda al final cambiar el nombre de tu instancia para que lleve el nombre de desarrollo, ya sea con NID o con una recreación de controlfile.

cinecomentado dijo...

OK, muchas gracias por la respuesta, Saludos!!

Ngl dijo...

Antes que nada Felicidadez por Tener este Blog, y otra Felicitacion, por la muy buena explicacion encuanto a este tema. Sabes soy nuevo en el mundo de oracle, y me tiraron al ruedo de Dba, y mi punto principal son los respaldos;Como comentas, es el pilar de todo, de que sirve un respaldo si no se puede utilizar.Confiezo no se nada del RMAN, todos mis respaldos los hago con Export, pero voy a ver como utilziar segun tu explicacion el dicho comando...GRACIAS.

Hugo E. Contreras Gamiño dijo...

Gracias por el comentario NGL, hay que tener mucho cuidado con los exports, ya que nos son respaldos físicos, son lógicos y pudieran causarte muchos problemas, te pongo un ejemplo: Una base de datos de 600 GB, el export toma 10 horas, el import toma aproximadamente 40 horas (esto con mucha ayuda de crear índices en paralelo). Digamos que el respaldo físico toma 4 horas y el restore 6 horas.

Erika Müdespacher dijo...

Hola Hugo.
Me gusta mucho tu blog, gracias por compartir con nosotros tus experiencias.
¿Nos podrías explicar en algun otro post como obtener la información de los índices si perdimos la tabla?

Saludos!

Anónimo dijo...

Saludos cordiales, aunque no es el tema del foro, favor ayudenme: Estoy empezando mi trabajo de DBA y como para darme la bienvenida veo que los datafile USERS.DBF y SYSTEM.dbf están dañados a causa de que están en sectores dañados del disco duro. Tengo un .DMP sin errores. Pueden darme una mano a ver si la base puedo subirla en otro servidor hasta arreglar el disco dañado? Si pueden ayudarme les dejo mi correo cacfhe@hotmail.com

Rocio Baez dijo...

Ante todo reciba cordiales saludos sr. Contreras, lo felicito por su post, esta bien explicado.

Anónimo dijo...

hola,

Trabajo con una BDD de oracle y me interesa usar el RMAN como backup. ¿que requisitos necesito? Me han hablado de una máquina independiente, ¿es necesario?

Un saludo

Lecter23 dijo...

Gran manual. Aporto una guía rápida que hice. Espero que les sirva de ayuda.

Manual de RMAN

Está en castellano, con ejemplos básicos.

Saludos