RMAN

Mostrando las entradas con la etiqueta RMAN. Mostrar todas las entradas
Mostrando las entradas con la etiqueta RMAN. Mostrar todas las entradas

miércoles, 1 de julio de 2026

El valor de los Backups Incrementales ante un borrado accidental de Archivelogs


Durante los procesos de migración de bases de datos Oracle, la gestión del espacio en la Flash Recovery Area (FRA) suele volverse crítica debido a la alta generación de Archive Logs. En escenarios de alta presión, es común recurrir a comandos manuales de depuración. Sin embargo, el uso descuidado de la cláusula FORCE puede derivar en un escenario catastrófico.

En este artículo analizaremos cómo un borrado forzado de secuencias de Archive Logs afectó un respaldo de migración en ejecución, y cómo la ejecución de un Backup Incremental Level 1 actuó como salvavidas para mantener la disponibilidad de los datos.

El objetivo era generar un respaldo completo para mover la base de datos hacia un nuevo servidor. Debido al alto volumen de transacciones, la FRA comenzó a quedarse sin espacio. Para mitigar esto, se procedió a respaldar los logs directamente hacia un Filesystem alterno para liberar espacio local.

Para acelerar la depuración, se optó por eliminar los Archive Logs basándose en rangos de secuencias (sequence) en lugar de la cláusula habitual por tiempo (BEFORE 'SYSDATE'), aplicando además el parámetro FORCE:

RMAN> DELETE FORCE ARCHIVELOG FROM SEQUENCE 12345 UNTIL SEQUENCE 12355;


⚠️ El Peligro del Modificador FORCE: > El parámetro FORCE de RMAN ejecuta un borrado físico e ignora si los archivos están catalogados correctamente o si residen en múltiples destinos. Al ejecutarlo, RMAN no solo eliminó las secuencias de la FRA, sino que también barrió con las copias de esos mismos Archive Logs que ya se habían respaldado en la ruta del Filesystem destinada a la migración.

Dado que en ese instante se estaba ejecutando el Backup Full (Level 0) base para la migración, la pérdida de estos Archive Logs comprometía la consistencia del respaldo para el posterior RESTORE y RECOVER en el destino. La ventana de mantenimiento parecía perdida.

Originalmente, la estrategia no contemplaba el uso de respaldos incrementales. Sin embargo, ante la crisis, se optó por una solución alternativa basada en la arquitectura de RMAN:

  • Archive Logs: Registran de manera lineal y cronológica los cambios vectoriales aplicados en la base de datos.

  • Backup Incremental Level 1: Captura el estado final de los bloques de datos que sufrieron modificaciones desde el último Level 0.

Para salvar la situación, inmediatamente después de que finalizó el Backup Full, se lanzó de manera manual un Backup Incremental:

RMAN>BACKUP INCREMENTAL LEVEL 1 DATABASE FORMAT '/ruta_de_backup/db_inc_%u';

Al ejecutarse en ese instante, el Level 1 escaneó los datafiles y capturó en un conjunto de respaldos consolidado los bloques que habían cambiado. De esta manera, los cambios atrapados en la brecha de los Archive Logs destruidos quedaron asegurados directamente a nivel de bloques de datos.


Al realizar la restauración en el nuevo servidor, la ausencia de las secuencias de Archive Logs eliminadas por error no detuvo el proceso.
RMAN> RESTORE DATABASE;
RMAN> RECOVER DATABASE;

Durante el paso de RECOVER, RMAN detectó la existencia del Backup Incremental Level 1. En lugar de detenerse inmediatamente solicitando las secuencias perdidas, RMAN aplicó directamente los bloques modificados del archivo incremental sobre el Backup Level 0 restaurado.

Esto consolidó los cambios pendientes directamente en los datafiles, permitiendo alcanzar la consistencia requerida para abrir la base de datos de manera segura:

SQL> ALTER DATABASE OPEN RESETLOGS;

Este escenario demuestra que el Backup Incremental Level 1 es una excelente herramienta de contingencia para mitigar rupturas en la cadena de redo histórica, reduciendo drásticamente el RTO al consolidar cambios directamente a nivel de bloques. Sin embargo, para salvaguardar la integridad de la estrategia de recuperación, se debe desterrar el uso reactivo de DELETE FORCE para liberar espacio en la FRA durante operaciones en caliente, ya que RMAN puede eliminar copias válidas en otros destinos activos. En su lugar, la buena práctica exige dimensionar correctamente la FRA antes de la migración, priorizar comandos de cambio de catálogo (CROSSCHECK y DELETE EXPIRED) o reubicar temporalmente los destinos de los logs (LOG_ARCHIVE_DEST_n) hacia un storage externo sin romper la consistencia del respaldo base.

Saludos.


viernes, 27 de febrero de 2026

De 12c a 19c: Guía de Migración y Upgrade mediante RMAN (Método Manual)


A todos nos ha pasado que, dentro de las tareas que desempeña un DBA, está la de "actualizar la versión del motor" a una superior, ya sea por temas de obsolescencia, bugs, fin de soporte, etc.

Recientemente, me tocó actualizar y migrar hacia otro servidor una de las bases de datos que administro. Esta decisión no fue opcional: la versión 12c ya no cuenta con soporte oficial de Oracle para parches de seguridad y el sistema operativo del servidor original presentaba vulnerabilidades críticas debido a su antigüedad.

Lo primero que realicé fue verificar el modo de operación de la base de datos. Una de las estrategias clave para mantener el mínimo de indisponibilidad (downtime) es trabajar con la base de datos en modo ARCHIVELOG.

¿Por qué es esto vital? Porque nos permite definir un punto de corte claro y realizar el cambio (switchover) de forma controlada. Al tener los archivelogs activos, podemos asegurar que no se pierda ni una sola transacción durante el proceso de movimiento entre servidores.

Luego de ello, me enfoqué en generar el respaldo de la base de datos desde rman, dejo por aquí el código que utilicé, deben reemplaza nombre_de_tu_base por el nombre de la base de datos:


RESPALDO:

         backup_database.sh

export ORACLE_SID=nombre_de_tu_base
export ORACLE_BASE=/oracle/oracle/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/12.2.0/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH
export NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'
rman target / log=/backups/RMAN/backup_nombre_de_tu_base.log << EOF
run
{
CONFIGURE DEVICE TYPE DISK BACKUP TYPE TO COMPRESSED BACKUPSET;
CONFIGURE CHANNEL DEVICE TYPE DISK MAXPIECESIZE 4G;
allocate channel c1 device type disk;
allocate channel c2 device type disk;
allocate channel c3 device type disk;
allocate channel c4 device type disk;
backup spfile format '/backups/RMAN/nombre_de_tu_base_spfile_%u';
backup filesperset=4 database format '/backups/RMAN/nombre_de_tu_base_datafiles_%U';
backup current controlfile format '/backups/RMAN/nombre_de_tu_base_control-%U';
backup archivelog all format '/backups/RMAN/nombre_de_tu_base_arc_%U';
release channel c1;
release channel c2;
release channel c3;
release channel c4;
}
exit;
EOF

Ejecutamos el proceso de respaldo con el comando:

nohup sh backup_database.sh &

Un vez finalizado el proceso de respaldo, en el directorio encontraremos archivos nombrados como: nombre_de_tu_base_spfile, nombre_de_tu_base_datafiles, nombre_de_tu_base_control, nombre_de_tu_base_arc.


Procedemos a ejecutar la restauración de la base en un home 19c con el backup generado en la versión 12c.


RESTAURACIÓN:

Creamos un init.ora para nuestra base de datos en el nuevo servidor en la ruta: /oracle/oracle/app/oracle/product/19.0.0/db_home/dbs

            init.ora

*.audit_file_dest='/oracle/oracle/app/oracle/oracle_base/admin/nombre_de_tu_base/adump'
*.audit_trail='db'
*.control_files='+GDATA','+GFRA'
*.db_block_size=8192
*.db_name='nombre_de_tu_base'
*.db_unique_name='nombre_de_tu_base'
*.compatible='12.2.0'
*.db_files=2000
*.db_recovery_file_dest='+GFRA'
*.db_recovery_file_dest_size=2000g
*.diagnostic_dest='/oracle/oracle/app/oracle/oracle_base'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=dbgenXDB)'
*.nls_language='AMERICAN'
*.nls_territory='AMERICA'
*.open_cursors=300
*.pga_aggregate_target=15g
*.processes=2600
*.remote_login_passwordfile='EXCLUSIVE'
*.sga_target=50g
*.undo_tablespace='UNDOTBS1'

IMPORTANTE: Asegúrate de que el parámetro compatible en tu init.ora sea exactamente el mismo que tenía la base de datos origen (ej. 12.2.0).  

Si no existe, procedemos a crear la carpeta adump:
mkdir /oracle/oracle/app/oracle/oracle_base/admin/nombre_de_tu_base/adump -p

Iniciamos la base de datos en modo no mount:

STARTUP NOMOUNT PFILE='/oracle/oracle/app/oracle/product/19.0.0/db_home/dbs/initdnombre_de_tu_base.ora';

 Restauramos los control file, usualmente el archivo contiene la palabra *control*:

rman target /
restore controlfile from '/backups/RMAN/nombre_de_tu_base_control-gk4b2vc8_1_1';

El paso anterior nos dará la ruta donde se han restaurado los control file, las cuales deberemos copiar y reemplazar en nuestro init.ora

output file name=+GDATA/NOMBRE_DE_TU_BASE/CONTROLFILE/current.261.1219619035
output file name=+GFRA/NOMBRE_DE_TU_BASE/CONTROLFILE/current.508.1219619037 

 Apagamos la base de datos para modificar el init.ora

shutdown immediate;

Modificamos en el init.ora el apartado de *.control_files con las rutas del anterio paso.

vi init.ora

*.control_files='+GDATA/nombre_de_tu_base/CONTROLFILE/current.258.1217774787','+GFRA/nombre_de_tu_base/CONTROLFILE/current.256.1217774787'

Iniciamos la base de datos en modo mount.

STARTUP MOUNT PFILE='/oracle/oracle/app/oracle/product/19.0.0/db_home/dbs/init.ora';

Creamos nuestro SPFILE a partir de nuestro PFILE (init.ora).

 CREATE SPFILE FROM PFILE='/oracle/oracle/app/oracle/product/19.0.0/db_home/dbs/init.ora';

Catalogamos los datafiles desde RMAN.

rman target /
CATALOG START WITH '/backups/RMAN/';
yes

 Sincronizamos el catalogo de respaldos y eliminamos los que se encuentren en estado expirado.

crosscheck backup;
delete noprompt expired backup; 

Sincronizamos el catalogo de archivelogs y eliminamos los que se encuentren en estado expirado.

crosscheck archivelog all;
delete noprompt expired archivelog all;

 Creamos el script bash para restaura la base de datos.

        restore_database.sh

export ORACLE_SID=nombre_de_tu_base
export ORACLE_BASE=/oracle/oracle/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/19.0.0/db_home
export PATH=$ORACLE_HOME/bin:$PATH
export NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'
rman target / log=/oracle/oracle/restore_database.log <<EOF
run
{
allocate channel c1 device type disk;
allocate channel c2 device type disk;
allocate channel c3 device type disk;
allocate channel c4 device type disk;
allocate channel c5 device type disk;
allocate channel c6 device type disk;
allocate channel c7 device type disk;
allocate channel c8 device type disk;
set newname for database to '+GDATA';
restore database;
switch datafile all;
recover database;
release channel c1;
release channel c2;
release channel c3;
release channel c4;
release channel c5;
release channel c6;
release channel c7;
release channel c8;
}
exit;
EOF 

Ejecutamos el proceso de restauración con el comando:

nohup sh restore_database.sh &

Catalogamos los archivelogs y procedemos a aplicar para terminar de sincronizar la base de datos.

rman target /
CATALOG START WITH '/backups/RMAN/ARCHIVELOG';
yes
recover database;
Apagamos la base de datos y la iniciamos en modo UPGRADE para proceder con la actualización.
sqlplus / as sysdba
SHUTDOWN IMMEDIATE;
STARTUP UPGRADE;
exit

IMPORTANTE: No intentes un ALTER DATABASE OPEN RESETLOGS convencional, ya que fallará debido a la diferencia de versiones del diccionario.

ACTUALIZACIÓN:

Con esto podemos iniciar el upgrade de la base de datos, es necesario dar permisos de ejecución al utilitario de upgrade.

chmod u+x $ORACLE_HOME/rdbms/admin/catctl.pl

 Antes de realizar el upgrade, necesitas saber si tu base de datos cumple con los requisitos mínimos. Oracle proporciona un archivo Java llamado preupgrade.jar

$ORACLE_HOME_19c/jdk/bin/java -jar $ORACLE_HOME_19c/rdbms/admin/preupgrade.jar terminal

Ejecutar el utilitario de upgrade database desde linux y guardar la ejecución en un log. Podemos colocarle 4 hilos para que el proceso lo haga en menos tiempo, depende mucho de la capacidad computacional de tu servidor. 

        Con hilos:

nohup $ORACLE_HOME/rdbms/admin/catctl.pl -n 4 $ORACLE_HOME/rdbms/admin/catupgrd.sql > upgrade.log &

         Sin hilos:

nohup $ORACLE_HOME/rdbms/admin/catctl.pl $ORACLE_HOME/rdbms/admin/catupgrd.sql > upgrade.log &



Iniciamos la base de datos, dado que luego de la actualización se queda en estado shutdown.

sqlplus / as sysdba
startup;

Compilamos los objetos inválidos que desde SQLPlus tras la actualización.

@$ORACLE_HOME/rdbms/admin/utlrp.sql

 Ejecutamos la actualización del diccionario desde SQLPlus.

EXEC DBMS_STATS.GATHER_DICTIONARY_STATS;

Verificamos el estado final del registro de componentes para asegurarnos que todo quede en estado VALIDO.

COLUMN comp_name FORMAT A40
COLUMN version FORMAT A15
SELECT comp_name, version, status FROM dba_registry;

Cambiamos la compatibilidad a versión 19.0.0.0.0 para aprovechar todas la nuevas funciones que trae esta nueva versión.
ALTER SYSTEM SET compatible = '19.0.0.0.0' SCOPE=SPFILE;

IMPORTANTE: Cambia la compatibilidad a 19.0.0 una vez que el upgrade del diccionario haya finalizado con éxito. Este es el ÚLTIMO paso de todo el proceso.

Reiniciamos la base de datos para que tome efecto el cambio de la compatibilidad.

sqlplus / as sysdba
shutdown immediate;
startup;

Migrar y actualizar una base de datos de producción es siempre un reto que pone a prueba nuestra planificación. Aunque el método manual que hemos visto hoy nos da un control total y un entendimiento profundo de lo que sucede, siempre recomiendo automatizar estos pasos en entornos extensos utilizando la herramienta AutoUpgrade de Oracle.

Saludos,

Luis Felipe.