[OCI-26ai] Refreshable Clone PDBs
![[OCI-26ai] Refreshable Clone PDBs](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1766420197468%2F40e152f1-5bbb-49cc-b98b-878fb407105d.jpeg&w=3840&q=75)
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 MANUALDestino:
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 NONEAsí de sencillo podemos cambiar los roles.
Espero que os guste. ¡Nos vemos en el próximo artículo!
![[26ai] Hybrid Read-Only Mode PDB](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fuploads%2Fcovers%2F65605419d28f19cc44df7ef1%2Fde208bd2-5e24-4fd3-acf7-8e5394d95283.png&w=3840&q=75)
![[26ai] ALERT_LOG_MAX_SIZE](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fuploads%2Fcovers%2F65605419d28f19cc44df7ef1%2Fcbb365d0-4428-4a41-930d-516ce59e3355.jpg&w=3840&q=75)
![[26ai] ConnStr Tool](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fuploads%2Fcovers%2F65605419d28f19cc44df7ef1%2F5005f06e-946c-49ba-bfe8-7fe18d1075d9.png&w=3840&q=75)
![[26ai] Instalación de Oracle26ai en Linux 9](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fuploads%2Fcovers%2F65605419d28f19cc44df7ef1%2Fd9a6ba10-eb2d-4fee-8a0c-f4957cbdc676.png&w=3840&q=75)
![[OCI] Montaje de un Bucket como un FS](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fuploads%2Fcovers%2F65605419d28f19cc44df7ef1%2F05595570-0fbd-46ce-9db4-d2f0e9f09003.png&w=3840&q=75)