Skip to main content

Command Palette

Search for a command to run...

[OCI-26ai] Refreshable Clone PDBs

Updated
5 min read
[OCI-26ai] Refreshable Clone PDBs

El artículo también se encuentra publicado en Ingles English version.

En el artículo de hoy, vamos a ver como podemos realizar una copia de una PDB y mantenerla actualizada con el origen.

Este tipo de migración, la podemos realizar de manera local (dentro de la misma CDB) o de manera remota (otra CDB). En este artículo nos vamos a centrar en como hacerlo remotamente.

Otro punto que tenemos que tener en cuenta es que debemos tener configurado SEPS ya que vamos a definir las distintas PDB usando external store. En próximos artículos, os explicare como configurar este punto fácilmente.

Para poder llevar a cabo este laboratorio, vamos a definir dos máquinas virtuales, ambas con la última versión de Oracle en OCI.

Las máquinas que hemos definido son las siguientes:

  • Source: 26ai VM DB System Oracle Cloud (test_ORI).

  • Target: 26ai VM DB System Oracle Cloud (test_TARGET).

Y el modelo que vamos a seguir es el siguiente:

  • 1º: Definir la PDB REFRESH_PDB en TEST_ORI:
SQL> CREATE PLUGGABLE DATABASE REFRESH_PDB ADMIN USER admin IDENTIFIED BY admin;
Pluggable database created.
SQL> ALTER PLUGGABLE DATABASE REFRESH_PDB OPEN;
Pluggable database altered.
SQL> ALTER PLUGGABLE DATABASE REFRESH_PDB SAVE STATE;
Pluggable database altered.
SQL> SHOW PDBS

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         4 REFRESH_PDB                    READ WRITE NO
SQL> ! hostname
source
  • 2º: Comprobamos que no hay otra PDB, solo está la PDB$SEED.
SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
SQL> ! hostname
target
  • 3º: Definir un common user, no local user. El usuario debe llamarse igual y debe tener la misma contraseña en origen como destino.
SQL> CREATE USER C##MANAGER IDENTIFIED BY "XXXXXX";
User created.
SQL> GRANT CREATE SESSION, RESOURCE, CREATE ANY TABLE, UNLIMITED TABLESPACE TO C##MANAGER CONTAINER=ALL;
Grant succeeded.
SQL> GRANT CREATE PLUGGABLE DATABASE TO C##MANAGER CONTAINER=ALL;
Grant succeeded.
SQL> GRANT SYSOPER TO C##MANAGER CONTAINER=ALL;
Grant succeeded.
  • 4º: Definir los DB Links. Antes de definirlo, debemos modificar el tnsnames para incluir ambas cadenas de conexión.

Origen:

SQL> ! hostname
source

SQL> ! tail -8  $ORACLE_HOME/network/admin/tnsnames.ora
TARGET =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = XXXXXXXXXXXXXXXXXXXX)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XXXXXXXXXXXXXXXXXXXX)
    )
  )

Destino:

SQL> ! hostname
target
SQL> ! tail -8  $ORACLE_HOME/network/admin/tnsnames.ora
SOURCE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = XXXXXXXXXXXXXXXXXXXX)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XXXXXXXXXXXXXXXXXXXX)
    )
  )

Una vez que tenemos modificado el tnsnames, podemos definir el DB Link en target y en source.

SQL> CREATE DATABASE LINK DB_Source CONNECT TO C##MANAGER IDENTIFIED BY "XXXXXXXXX" USING 'SOURCE';
Database link created.
SQL> Select * From Dual@DB_Source;
D
-
X

Una vez que hemos comprobado que el DB funciona correctamente, ya podemos definir nuestra PDB.

La PDB en origen no contiene nada de información ahora mismo, así que vamos a definir algo en ella antes de clonarla.

SQL> alter session set container=REFRESH_PDB;
Session altered.
SQL> CREATE TABLE C##MANAGER.COPY_NUMERICOS AS 
     SELECT ROWNUM NUM 
       FROM DUAL 
    CONNECT BY ROWNUM <= 1000000;
Table created.
  • 5º: Procedemos a clonar nuestra PDB usando external store:
SQL> CREATE PLUGGABLE DATABASE REFRESH_PDB FROM REFRESH_PDB@DB_Source REFRESH MODE MANUAL keystore identified by external store;

Pluggable database created.

Si nos fijamos en la sentencia que hemos ejecutado, hemos indicado REFRESH MODE MANUAL.

Cuando definimos la PDB como REFRESH MODE MANUAL, la PDB no se actualiza de manera automática, en cambio si la definimos REFRESH MODE EVERY <min>, la PDB sí se actualiza de manera automática.

El estado de la PDB que nos marca DBA_PDBs es REFRESHING.

SQL> select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB';

    CON_ID PDB_NAME             STATUS               REFRESH_MODE         REFRESH_INTERVAL
---------- -------------------- -------------------- -------------------- ----------------
         3 REFRESH_PDB          REFRESHING           MANUAL

Abrimos las PDB en modo lectura y consultamos si la tabla se encuentra en la PDB

SQL> ALTER SESSION SET CONTAINER=REFRESH_PDB;
Session altered.
SQL> ALTER PLUGGABLE DATABASE OPEN READ ONLY;
Pluggable database altered.
SQL> SELECT COUNT(*) FROM C##MANAGER.COPY_NUMERICOS;

  COUNT(*)
----------
   1000000

Volvemos a insertar registros en la tabla y refrescamos de nuevo la PDB.

 SQL> ALTER PLUGGABLE DATABASE CLOSE IMMEDIATE;

Pluggable database altered.

SQL> ALTER PLUGGABLE DATABASE REFRESH;

Pluggable database altered.

SQL> ALTER PLUGGABLE DATABASE OPEN READ ONLY;

Pluggable database altered.

SQL>  SELECT COUNT(*) FROM C##MANAGER.COPY_NUMERICOS;

  COUNT(*)
----------
   2000000

Perfecto, tenemos ambas PDBs sincronizadas.

Como último paso, podemos hacer dos cosas:

  • Finalizar, es decir, que pase de refreshable clone a regular PDB:
SQL> ALTER PLUGGABLE DATABASE CLOSE IMMEDIATE;
Pluggable database altered.
SQL>  alter pluggable database refresh mode none;
Pluggable database altered.
SQL> ALTER PLUGGABLE DATABASE OPEN;
Pluggable database altered.

SQL> select con_id, pdb_name, status, refresh_mode, refresh_interval 
     from dba_pdbs where pdb_name='REFRESH_PDB';

    CON_ID PDB_NAME             STATUS               REFRESH_MODE         REFRESH_INTERVAL
---------- -------------------- -------------------- -------------------- ----------------
         3 REFRESH_PDB          NORMAL               NONE
  • Switch the roles: Nuestra PDB de source pasará de NORMAL a REFRESHING y la PDB de target de REFRESHING a NORMAL:

    Origen:

      SQL> col pdb_name format a15
      SQL>  set linesize 1000
      SQL> select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB';
    
          CON_ID PDB_NAME        STATUS     REFRES REFRESH_INTERVAL
      ---------- --------------- ---------- ------ ----------------
               4 REFRESH_PDB     NORMAL     NONE
    
      SQL> ALTER SESSION SET CONTAINER = REFRESH_PDB;                                                                 
    
      Session altered.
    
      SQL>  ALTER PLUGGABLE DATABASE REFRESH MODE MANUAL FROM REFRESH_PDB@DB_Target SWITCHOVER;
    
      Pluggable database altered.
    
      SQL> alter pluggable database open read only;
    
      Pluggable database altered.
    
      SQL> select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB';
    
          CON_ID PDB_NAME        STATUS     REFRES REFRESH_INTERVAL
      ---------- --------------- ---------- ------ ----------------
               4 REFRESH_PDB     REFRESHING MANUAL
    

    Destino:

      SQL> r
        1* select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB'
    
          CON_ID PDB_NAME        STATUS     REFRES REFRESH_INTERVAL
      ---------- --------------- ---------- ------ ----------------
               3 REFRESH_PDB     REFRESHING MANUAL
    
      SQL> alter pluggable database refresh_pdb open read only;
    
      Pluggable database altered.
    
      SQL> select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REFRESH_PDB';
    
          CON_ID PDB_NAME        STATUS     REFRES REFRESH_INTERVAL
      ---------- --------------- ---------- ------ ----------------
               3 REFRESH_PDB     NORMAL     NONE
    

    Así de sencillo podemos cambiar los roles.

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