Hacer Flashback a Base de Datos Oracle con DataGuard
Introducción
A veces, en una aplicación que está usando la base Primaria de Oracle DataGuard, las cosas pueden salir mal y nos pedirán que recuperemos la base de datos a un punto previo en el tiempo. Si sólo han pasado algunas horas podemos evitar una recuperación larga con RMAN
usando la funcionalidad de FLASHBACK
.
Vamos a probar si podemos hacer flashback de la instancia Primaria a un punto de restauración previo y luego hacer lo mismo con la instancia Standby evitando reconstruirla.
Ambiente
Usaremos un ambiente DataGuard con una instancia Primaria y una Physical Standby en Oracle 19c con una base de datos pluggable.
Prerrequisitos
Primero necesitamos validar que ambas bases, Primaria y Standby tienen habilitado el flashback:
[oracle@patodgprmy ~]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Wed May 6 13:52:36 2020
Version 19.3.0.0.0
SQL> select name, database_role, flashback_on from v$database;
NAME DATABASE_ROLE FLASHBACK_ON
--------- ---------------- ------------------
PRMYDB PRIMARY YES
[oracle@patodgstby trace]$ sqlplus / as sysdba
SQL> select name, database_role, flashback_on from v$database;
NAME DATABASE_ROLE FLASHBACK_ON
--------- ---------------- ------------------
PRMYDB PHYSICAL STANDBY YES
Preparar el Flashback
Crear un Punto de Restauración en la Primaria
Previo a la actividad que pudiera destruir los datos queremos configurar un punto de restauración al cual podremos regresar la base de datos:
[oracle@patodgprmy ~]$ sqlplus / as sysdba
SQL> create restore point FLASH_POINT GUARANTEE FLASHBACK DATABASE;
Restore point created.
Validar que la Replicación está Sincronizada
Última secuencia en la instancia Primaria:
[oracle@patodgprmy ~]$ sqlplus / as sysdba
SELECT ARCH.THREAD# Thread, ARCH.SEQUENCE# LastSequenceReceived, APPL.SEQUENCE# LastSequenceApplied, (ARCH.SEQUENCE# - APPL.SEQUENCE#) Difference FROM (SELECT THREAD# ,SEQUENCE# FROM V$ARCHIVED_LOG WHERE (THREAD#,FIRST_TIME ) IN (SELECT THREAD#,MAX(FIRST_TIME) FROM V$ARCHIVED_LOG GROUP BY THREAD#)) ARCH, (SELECT THREAD# ,SEQUENCE# FROM V$LOG_HISTORY WHERE (THREAD#,FIRST_TIME ) IN (SELECT THREAD#,MAX(FIRST_TIME) FROM V$LOG_HISTORY GROUP BY THREAD#)) APPL WHERE ARCH.THREAD# = APPL.THREAD# ORDER BY 1;
THREAD LASTSEQUENCERECEIVED LASTSEQUENCEAPPLIED DIFFERENCE
---------- -------------------- ------------------- ----------
1 7 7 0
Última secuencia en la instancia Standby:
[oracle@patodgstby ~]$ sqlplus / as sysdba
SELECT ARCH.THREAD# Thread, ARCH.SEQUENCE# LastSequenceReceived, APPL.SEQUENCE# LastSequenceApplied, (ARCH.SEQUENCE# - APPL.SEQUENCE#) Difference FROM (SELECT THREAD# ,SEQUENCE# FROM V$ARCHIVED_LOG WHERE (THREAD#,FIRST_TIME ) IN (SELECT THREAD#,MAX(FIRST_TIME) FROM V$ARCHIVED_LOG GROUP BY THREAD#)) ARCH, (SELECT THREAD# ,SEQUENCE# FROM V$LOG_HISTORY WHERE (THREAD#,FIRST_TIME ) IN (SELECT THREAD#,MAX(FIRST_TIME) FROM V$LOG_HISTORY GROUP BY THREAD#)) APPL WHERE ARCH.THREAD# = APPL.THREAD# ORDER BY 1;
THREAD LASTSEQUENCERECEIVED LASTSEQUENCEAPPLIED DIFFERENCE
---------- -------------------- ------------------- ----------
1 7 7 0
Perfecto, nuestras instancias están sincronizadas.
Destruir algunos Datos
En este ejemplo nuestro usuario se conectará a la base de datos pluggable y eliminará una tabla y borrará el contenido de una segunda tabla:
[oracle@patodgprmy ~]$ sqlplus /nolog
SQL> conn pato@taller;
Enter password:
Connected.
SQL> drop table t1 ;
Table dropped.
SQL> delete from t2 ;
5 rows deleted.
SQL> commit ;
Commit complete.
Validar los Datos Perdidos en la Standby
Deshabilitar la replicación y abrir la base Standby en modo lectura para validar:
[oracle@patodgstby ~]$ sqlplus / as sysdba
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
Database altered.
SQL> alter database open read only;
Database altered.
SQL> ALTER PLUGGABLE DATABASE taller OPEN;
Pluggable database altered.
SQL> alter session set container = taller;
Session altered.
SQL> select count(*) from pato.t1 ;
select count(*) from pato.t1
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> select count(*) from pato.t2 ;
COUNT(*)
----------
0
Sí, la tabla y los datos se perdieron también aquí. Habilitemos de nuevo la repliación y regresemos a la Primaria:
SQL> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount
ORACLE instance started.
Total System Global Area 1610609888 bytes
Fixed Size 9135328 bytes
Variable Size 956301312 bytes
Database Buffers 637534208 bytes
Redo Buffers 7639040 bytes
Database mounted.
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
Database altered.
Flashback DataGuard
Flashback en la Base de Datos Primaria
Valida que tengamos un punto de restauración y obtén el SCN
para su uso posterior en la Standby:
[oracle@patodgprmy ~]$ sqlplus / as sysdba
SQL> select NAME, SCN from v$restore_point;
NAME SCN
--------------- ----------
FLASH_POINT 2990133
Necesitamos detener la instancia(shutdown
) y luego montarla (startup mount
) para poder ejecutar el flashback database
y al final abriremos la base de datos con resetlogs
.
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount
ORACLE instance started.
Total System Global Area 1610609888 bytes
Fixed Size 9135328 bytes
Variable Size 989855744 bytes
Database Buffers 603979776 bytes
Redo Buffers 7639040 bytes
Database mounted.
SQL> flashback database to restore point FLASH_POINT;
Flashback complete.
SQL> alter database open resetlogs;
Database altered.
Validar los Datos Recuperados en la Base de Datos Primaria
[oracle@patodgprmy ~]$ sqlplus /nolog
SQL> conn pato@taller;
Enter password:
Connected.
SQL> select count(*) from t1;
COUNT(*)
----------
2
SQL> select count(*) from t2;
COUNT(*)
----------
5
Perfecto, la tabla y los datos fueron recuperados. Ahora creemos una nueva tabla para validar si la replicación está funcionando bien después de hacer flashback a la Standby:
SQL> create table t3 (i3 int, c3 varchar(20), d3 timestamp) ;
Table created.
SQL> insert into t3 values (1,'After flashback',current_timestamp);
1 row created.
SQL> commit ;
Commit complete.
Flashback en la Base de Datos Standby
Como los puntos de restauración no se replican, y tampoco configuramos un punto de restauración en la StandBy, vamos a regresar la base de datos a un SCN en particular.
Del punto de restauración en la Primaria sabemos que necesitamos regresar al SCN 2990133
, así que debemos validar si ese SCN está dentro del rango de flashback:
[oracle@patodgstby ~]$ sqlplus / as sysdba
SQL> select OLDEST_FLASHBACK_SCN from V$FLASHBACK_DATABASE_LOG;
OLDEST_FLASHBACK_SCN
--------------------
2989744
Nuestro punto SCN del flashback deseado es mayor al más antiguo, así que estamos dentro del rango y podemos continuar.
Detengamos la replicación, hagamos el flashback
de la Standby y habilitemos de nuevo la replicación:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
Database altered.
SQL> flashback standby database to SCN 2990133;
Flashback complete.
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
Database altered.
Validar los Datos Recuperados en la Base de Datos Standby
Démosle un tiempo a la Standby para que se sincronice y entonces cancelemos la recuperación y abramos la instancia en modo lectura:
[oracle@patodgstby ~]$ sqlplus / as sysdba
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
Database altered.
SQL> alter database open read only;
Database altered.
SQL> ALTER PLUGGABLE DATABASE taller OPEN;
Pluggable database altered.
y entonces validemos:
SQL> alter session set container = taller;
Session altered.
SQL> select count(*) from pato.t1 ;
COUNT(*)
----------
2
SQL> select count(*) from pato.t2 ;
COUNT(*)
----------
5
SQL> select * from pato.t3 ;
I3 C3 D3
---------- -------------------- --------------------------------
1 After flashback 06-MAY-20 02.25.41.879045 PM
Como podemos ver la tabla y los datos perdidos se recuperaron, pero también la nueva tabla generada después del flashback en la Primaria ha sido replicada.
Borrar el Punto de Restauración
No olvides borrar el punto de restauración usado para esta prueba:
[oracle@patodgprmy ~]$ sqlplus / as sysdba
SQL> DROP RESTORE POINT FLASH_POINT ;
Restore point dropped.
Conclusión
Como pudimos ver es posible realizar el flashback
de las bases de datos (Primaria and Standby) pertenecientes a un ambiente DataGuard.
Sólo nos tenemos que asegurar que ambas bases de datos tengan el flashback habilitado y que nuestro punto en el tiempo SCN esté dentro del rango disponible para hacer flashback.