# [OCI]19c Dataguard  y Physical Standby desde una Custom Image.

En el artículo de hoy vamos a definir un laboratorio con **Oracle Dataguard 19** en **OCI**. Con lo que necesitaremos definir dos **IaaS**.

La idea del laboratorio es la siguiente:

![](https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/bc3e1842-38cf-4bfc-b35b-e754a3003020.png align="center")

Como podemos ver, vamos a definir **dg-primary** y **dg-standby**. En este laboratorio, para no tener que hacer dos configuraciones, lo que haremos es configurar en **dg-primary** casi todo y crear una **Custom image** en **OCI** antes de crear la base de datos. Definiremos **dg-standby** basándonos en la imagen que hemos definido, tampoco vamos a crear ninguna base de datos ahí, sino que haremos directamente un ***rman duplicate from active databas*e**.

Así que vamos ello.

### dg-primary

De esta máquina es donde vamos a definir nuestra **Custom image**. Pero antes de ese paso, necesitamos configurarlo todo sin crear la base de datos.

Los pasos que vamos hacer a grandes rasgos son:

![](https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/8808c74e-31b2-497f-adf7-7f0382208628.png align="center")

Es decir:

- **Preinstall-19c**. Una vez instalado, definiremos los directorios de **oracle** junto con la definición de las variables en el **.bashrc**.

```shell
[root@primary ~]$ dnf update -y
[root@primary ~]$ dnf install -y oracle-database-preinstall-19c
[root@primary ~]$ mkdir -p /u01/app/oracle/product/19.0.0/dbhome_1
[root@primary ~]$ mkdir -p /u01/app/oraInventory
[root@primary ~]$ mkdir -p /u01/software
[root@primary ~]$ chown -R oracle:oinstall /u01
[root@primary ~]$ chmod -R 775 /u01 
```

- **Unzip 19.3**, descargamos de [aquí](https://www.oracle.com/database/technologies/oracle19c-linux-downloads.html) la versión.

```shell
[oracle@primary ~]$ mv /tmp/LINUX.X64_193000_db_home.zip /u01/software/
[oracle@primary ~]$ cd $ORACLE_HOME
[oracle@primary ~]$ unzip /u01/software/LINUX.X64_193000_db_home.zip
```

- Actualizamos **oPatch** (*Path 6880880*).

```shell
[oracle@primary ~]$ cd $ORACLE_HOME
[oracle@primary ~]$ mv OPatch OPatch.old
[oracle@primary ~]$ unzip /tmp/p6880880_190000_Linux-x86-64.zip 
[oracle@primary dbhome_1]$ $ORACLE_HOME/OPatch/opatch version
OPatch Version: 12.2.0.1.55

OPatch succeeded.
```

- **Unzip RU**, en este caso la **RU 19.32** (*Path 39472050* ). Actualmente ya esta la **RU 19.33**, pero eso la dejaremos para más adelante.

```shell
[oracle@primary software]$ unzip /tmp/p39472050_190000_Linux-x86-64.zip 
```

Además vamos aplicar los siguientes **one-offs** que Oracle nos indica.

![](https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/df239f56-c685-43ff-ad84-0b8aed0ca86c.png align="center")

Esta información se puede consultar [aquí](https://docs.oracle.com/en/database/oracle/oracle-database/19/rnrdm/installing-oracle-database-19c-oracle-linux-9-and-red-hat-enterprise-linux-9.html).

Con lo que descargamos a mayores los parches: *39932578*,*39544247* y *39388682*.

```shell
[oracle@primary software]$ unzip /tmp/p39388682_1932000DBRU_Generic.zip
[oracle@primary software]$ unzip /tmp/p39544247_1932000DBRU_Linux-x86-64.zip
[oracle@primary software]$ unzip /tmp/p39932578_1932000OCWRU_Linux-x86-64.zip
```

- **runInstaller** en modo **silent**.

```sql
[oracle@primary software]$ cd $ORACLE_HOME
[oracle@primary software]$ ./runInstaller \
  -silent \
  -waitforcompletion \
  -applyRU /u01/software/39472050 \
  -applyOneOffs /u01/software/39932578,/u01/software/39544247,/u01/software/39388682 \
  oracle.install.option=INSTALL_DB_SWONLY \
  UNIX_GROUP_NAME=oinstall \
  INVENTORY_LOCATION=/u01/app/oraInventory \
  ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1 \
  ORACLE_BASE=/u01/app/oracle \
  oracle.install.db.InstallEdition=EE \
  oracle.install.db.OSDBA_GROUP=dba \
  oracle.install.db.OSOPER_GROUP=oper \
  oracle.install.db.OSBACKUPDBA_GROUP=backupdba \
  oracle.install.db.OSDGDBA_GROUP=dgdba \
  oracle.install.db.OSKMDBA_GROUP=kmdba \
  oracle.install.db.OSRACDBA_GROUP=racdba \
  SECURITY_UPDATES_VIA_MYORACLESUPPORT=false \
  DECLINE_SECURITY_UPDATES=true
```

Verificamos:

```sql
[oracle@primary ~]$ sqlplus -v

SQL*Plus: Release 19.0.0.0.0 - Production
Version 19.32.0.0.0
```

### **Custom image en OCI**

Ahora que ya tenemos la máquina lista, es decir, sin crear la base de datos, es el momento de definir la imagen.

En **OCI**, en los detalles de la instancia, hacemos lo siguiente:

![](https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/9dd59310-df08-4a4c-bc2e-b6030720ab0e.png align="center")

Una vez creada, para ver nuestra imagen vamos a *Compute> Custom Images*:

![](https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/ff0507fb-d34e-48ec-8a09-161157980b2f.png align="center")

Ahí vemos la imagen que acabamos de definir:

![](https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/16ca6aa9-8532-4c0f-a7cf-7a9d1a4ae809.png align="center")

### **dg-standby**

Ahora definiremos la **standby** partiendo de la imagen que hemos definido previamente.

Cuando estamos definiendo la **IaaS**, donde pone **change image**, pulsamos ahí:

![](https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/a4a288f8-b76a-4e3d-b4b9-9eda7f335eac.png align="center")

Ahí nos aparece la siguiente ventana, iríamos a **My Images** y seleccionamos la **Custom image**:

![](https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/316bdde6-193c-4579-84f5-297d271a2a87.png align="center")

El resto de detalles lo ponemos acorde a nuestra **tenancy**.

Una vez terminado la creación de la **IaaS**, verificamos:

```shell
[oracle@dg-standby ~]$ sqlplus -v

SQL*Plus: Release 19.0.0.0.0 - Production
Version 19.32.0.0.0
```

### Creación de CDB1

Vamos a definir la base de datos con **dbca** en modo **silent** en **dg-primary**.

```shell
[root@primary ~]# su - oracle
[oracle@primary ~]$ export ORACLE_SID=CDB1
[oracle@primary ~]$ 
$ORACLE_HOME/bin/dbca -silent -createDatabase \
  -templateName General_Purpose.dbc \
  -gdbName CDB1 \
  -sid CDB1 \
  -createAsContainerDatabase true \
  -numberOfPDBs 1 \
  -pdbName PDB1 \
  -useLocalUndoForPDBs true \
  -sysPassword 'XXXXXX' \
  -systemPassword 'XXXXXX' \
  -pdbAdminPassword 'XXXXXX' \
  -databaseConfigType SINGLE \
  -storageType FS \
  -datafileDestination /u01/app/oracle/oradata \
  -useOMF true \
  -recoveryAreaDestination /u01/app/oracle/fast_recovery_area \
  -recoveryAreaSize 10240 \
  -enableArchive true \
  -archiveLogMode AUTO \
  -memoryMgmtType AUTO_SGA \
  -characterSet AL32UTF8 \
  -emConfiguration NONE
```

Verificamos al finalizar:

```sql
[oracle@primary ~]$ sqlplus / as sysdba
SQL> 
   Select name, 
          db_unique_name, 
          database_role, 
          open_mode, 
          log_mode, 
          force_logging
    From v$database

NAME	  DB_UNIQUE_NAME		 DATABASE_ROLE	  OPEN_MODE	       LOG_MODE     FORCE_LOGGING
--------- ------------------------------ ---------------- -------------------- ------------ ---------------------------------------
CDB1	  CDB1				 PRIMARY	  READ WRITE	       ARCHIVELOG   NO
```

Activamos el **Force Logging**:

```sql
SQL> Alter Database Force Logging;

Database altered.

SQL> Select force_logging From v$database;

FORCE_LOGGING
---------------------------------------
YES
```

### dg-primary: Pasos previos

El primer paso, es verificar la parte de los **Redo Logs**.

```sql
SQL> 
Select group#, 
       thread#, sequence#, bytes/Power(1024,2) as MB, 
       members, 
       status
  From v$log
 Order By thread#,group#;   

    GROUP#    THREAD#  SEQUENCE#	 MB    MEMBERS STATUS
---------- ---------- ---------- ---------- ---------- ----------------
	 1	    1	      16	200	     2 CURRENT
	 2	    1	      14	200	     2 INACTIVE
	 3	    1	      15	200	     2 INACTIVE
```

Definimos **Standby Redo Logs** con el mismo tamaño, es decir, 200Mb:

```sql
 Alter Database Add Standby Logfile Thread 1 Size 200M;
 Alter Database Add Standby Logfile Thread 1 Size 200M;
 Alter Database Add Standby Logfile Thread 1 Size 200M;
 Alter Database Add Standby Logfile Thread 1 Size 200M;
```

Configuramos el parámetro **log_archive_config**:

```sql
Alter System Set Log_Archive_Config='DG_CONFIG=(CDB1,CDB1_STBY)' Scope=Both;
```

Configuramos el parámetro **log_archive_dest**:

```sql
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=CDB1' SCOPE=BOTH;
```

Configuramos el parámetro **standby_file_management**:

```sql
alter system set standby_file_management=AUTO scope=both;
```

Configuramos el parámetro **fal_server**:

```sql
alter system set fal_Server='CDB1_STBY' scope=both;
```

Modificamos el **tnsnames** para incluir ambas cadenas y probamos que tenemos conexión en ambos sentidos.

```shell
[oracle@primary ~]$ grep -E "CDB1" $ORACLE_HOME/network/admin/tnsnames.ora
CDB1 =
      (SERVICE_NAME = CDB1)
CDB1_STBY =
      (SERVICE_NAME = CDB1_STBY)

[oracle@primary ~]$ tnsping CDB1_STBY
...
...
OK (10 msec)

[oracle@dg-standby ~]$ tnsping CDB1
...
...
OK (0 msec)
```

Copiamos el **password file** de **primary** a **standby**:

```sql
[oracle@primary ~]$ scp $ORACLE_HOME/dbs/orapwCDB1 oracle@dg-standby:/tmp/orapwCDB1
[oracle@dg-standby ~]$ mv /tmp/orapwCDB1 $ORACLE_HOME/dbs/
```

Creamos un **pfile** en la **standby** para poder arrancar en **nomount**.

```sql
[oracle@dg-standby ~]$ cat $ORACLE_HOME/dbs/initCDB1.ora
*.db_name='CDB1'
*.db_unique_name='CDB1_STBY'
*.enable_pluggable_database=TRUE

[oracle@dg-standby ~]$ export ORACLE_SID=CDB1
[oracle@dg-standby ~]$ sqlplus / as sysdba
SQL> startup nomount;
ORACLE instance started.
```

Perfecto, ahora vamos a probar a conectarnos desde la **primary** a la **standby:**

```sql
[oracle@primary ~]$ sqlplus sys@CDB1_STBY as sysdba
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.32.0.0.0
```

Validamos al contrario, desde la **standby** a la **primary**

```sql
[oracle@dg-standby ~]$ sqlplus conn sys@CDB1 as sysdba
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.32.0.0.0
```

Genial, tenemos comunicación en ambos sentidos.

En este punto estamos así, es decir, listo para lanzar el **duplicate**.

![](https://cdn.hashnode.com/uploads/covers/65605419d28f19cc44df7ef1/111d191e-7d72-4649-9b3f-5700491c7347.png align="center")

### RMAN ACTIVE DUPLICATE

Este es el comando que vamos a ejecutar:

```sql
[oracle@primary ~]$ rman target sys@CDB1 auxiliary sys@CDB1_STBY
RMAN>
DUPLICATE TARGET DATABASE
  FOR STANDBY
  FROM ACTIVE DATABASE
  USING BACKUPSET
  DORECOVER
  SPFILE
    SET DB_UNIQUE_NAME='CDB1_STBY'
    SET LOG_ARCHIVE_DEST_1=
      'LOCATION=USE_DB_RECOVERY_FILE_DEST
       VALID_FOR=(ALL_LOGFILES,ALL_ROLES)
       DB_UNIQUE_NAME=CDB1_STBY'
    SET FAL_SERVER='CDB1'
  NOFILENAMECHECK;
```

Una vez finalizado, verificamos en **dg-standby**:

```sql
[oracle@dg-standby ~]$ sqlplus / as sysdba
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.32.0.0.0

SQL> SELECT name, db_unique_name, database_role, open_mode FROM v$database;  

NAME	  DB_UNIQUE_NAME		 DATABASE_ROLE	  OPEN_MODE
--------- ------------------------------ ---------------- ------------------
CDB1	  CDB1_STBY			 PHYSICAL STANDBY MOUNTED
```

Habilitamos el envío de redo desde **primary** hacia **dg-standby**:

```sql
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=CDB1_STBY ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=CDB1_STBY' SCOPE=BOTH;

ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2=ENABLE SCOPE=BOTH;
```

En **dg-standby,** arrancamos el **redo apply** :

```sql
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
```

Activamos el **broker** tanto en **primary** como **dg-standby**.

```sql
ALTER SYSTEM SET DG_BROKER_START=TRUE SCOPE=BOTH;
```

Como último paso, configuramos el broker en la **primary**

```shell
[oracle@primary ~]$ dgmgrl sys@CDB1
DGMGRL> CREATE CONFIGURATION DG_CONFIG AS PRIMARY DATABASE IS CDB1 CONNECT IDENTIFIER IS CDB1;
DGMGRL> ADD DATABASE CDB1_STBY  AS CONNECT IDENTIFIER IS CDB1_STBY MAINTAINED AS PHYSICAL;
DGMGRL> ENABLE CONFIGURATION;
DGMGRL> SHOW CONFIGURATION;

Configuration - dg_config

  Protection Mode: MaxPerformance
  Members:
  cdb1      - Primary database
    cdb1_stby - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 40 seconds ago)

DGMGRL> 
```

Espero que os guste. ¡Nos vemos en el próximo artículo!
