Introduction
I have provided help for some people from GUOB community a few times with questions about “how to clone a PDB in CDB with Data Guard” or situations like “my standby stop to sync after a PDB clone at primary”. In this blog post I’m gonna to show an example in how I usually do this kind of PDB clone in CDB running in Data Guard configurations.
First thing to know is Oracle will not automatically create the new datafiles in the Standby when you clone a PDB in the Primary side, the only thing that Data Guard take care is about the PDB registration in the Standby controlfile. This occurs because Data Guard only send redo data from Primary to Standby, and when we are cloning a PDB, which usually occurs behind of scenes is a RMAN restore that do not generates redo to create the new datafiles. The only redo generated for this operation is the “PDB creation” itself, the information that is registered in the controlfile.
So when we clone a PDB in the Primary, we need to clone it in the Standby as well. Fortunately we can leverage the RESTORE FROM SERVICE feature in RMAN on Standby side. This is my preferred option and is that one I will demonstrate in this blog post.
Please note these steps were very tested in 19c databases, I didn’t have chance to test it in new releases like 26ai, but it is expected to work in the same way.
Case Scenario
To demonstrate how this works, I’m using an example of cloning a non-CDB database as a PDB in an existing CDB. This scenario is similar to the local PDB clone, but we need to use a DBLINK created in the Target CDB pointing to the source non-CDB database.
The next steps is divided in 3 sections:
- Section A – The commands we need to execute in the source non-CDB
- Section B – The commands we need to execute in the target Primary CDB
- Section C – The commands we need to execute in the target Standby CDB
To better understand this step by step, please keep in mind those details:
| Source non-CDB Hostname | lab03 |
| Source non-CDB Database name | DB03A |
| Target Primary CDB Hostname | lab01 |
| Target Standby CD Hostname | lab02 |
| Target Primary CDB Database unique name | CDBDG_A |
| Target Standby CDB Database unique name | CDBDG_B |
| Target new Clone PDB Name | DB03A_CLONE |
Step by Step
Section A) Source non-CDB
1) Create the clone user in the source non-CDB with the required privileges to create pluggable databases (this is required in order to clone the database over DBLINK):
create user c##clone_user identified by oracle; grant create session, sysoper, create pluggable database to c##clone_user;
Section B) Target CDB Primary
2) Create the DBLINK in the target CDB pointing to the source non-CDB:
drop public database link LK_TO_DB03A; create public database link LK_TO_DB03A connect to c##clone_user identified by oracle using '//lab03:1521/DB03A';
Please note I’m using EZCONNECT for the connection string, but you can use TNS alias as well.
3) Create the PDB clone
create pluggable database DB03A_CLONE from non$cdb@LK_TO_DB03A parallel 8;
I’m using PARALLEL 8 here. This is optional, but I always use this when that is possible.
4) Check the PDB status after the clone is completed:
set lines 300 col pdb_name for a20 col status for a20 col refresh_mode for a20 col refresh_interval for 999 select con_id, pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='DB03A_CLONE';
Also check for any PDB invalidation:
set pagesize 500 set linesize 300 col cause for a30 col name for a20 col message for a80 word_wrapped col status format a10 select name,cause,type,message,status from PDB_PLUG_IN_VIOLATIONS where status <> 'RESOLVED' order by name, type, cause;
That is expected the new PDB is in RESTRICTED mode due the pending task to convert it to PDB using the noncdb_to_pdb.sql script (next step)
5) Complete the conversion from non-CDB to PDB:
alter session set container = DB03A_CLONE; @?/rdbms/admin/noncdb_to_pdb.sql
6) Restart the PDB without restrictions or violations
alter pluggable database close; alter pluggable database open; show pdbs;
If the PDB still in RESTRICTED mode, so you should evaluate what is the cause using the PDB_PLUG_IN_VIOLATIONS view. For example, a common issue is a patch mismatch between the CDB root and the new PDB, where the solution is just to run the Datapatch.
Section C) Target CDB Standby
7) Check the status for the new PDB datafiles in the Standby:
alter session set container=DB03A_CLONE; set lines 100 col name format a20 select name, recovery_status from v$pdbs; set lines 120 set pages 9999 col name format a65 select name, status from v$datafile;
8) Execute an Active Restore for this PDB from Primary to Standby using RMAN
Connect in the RMAN:
rman connect target sys/<sysPassword>@CDBDG_B
Execute a script like this, please change the PDB name, the disk group and connection string according:
run{
allocate channel disk1 device type disk;
allocate channel disk2 device type disk;
allocate channel disk3 device type disk;
allocate channel disk4 device type disk;
allocate channel disk5 device type disk;
set newname for pluggable database DB03A_CLONE to '+DATA';
restore pluggable database DB03A_CLONE from service 'lab01:1521/CDBDG_A' section size 512m;
}
What is important to note here:
- The TNS used as ‘target’ is the current Standby
- The TNS used as ‘from service’ is the current Primary
- “set newname” it is important here to leverage the RMAN capability of generating OMF names for restored datafiles
- “section size” it is important if the PDB has big files, but I normally use this option even for small files. If your datafiles are really big, like 16-32 TB, consider to use larger sections like 128 – 256 GB.
- The number of channel should be allocated as you usually would allocate to an active duplicate from PROD.
- If the Primary database is RAC, use the SCAN instead of hostname to balance the load in the Primary cluster.
9) Stop MRP. In this example I’m doing this manually using SQLPLUS, but we can use dgmgrl for Data Guard with Broker configuration:
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
10) Switch the Standby datafiles to their copies (this actually rename the datafiles in the standby controlfile).
This is a RMAN command:
switch pluggable database DB03A_CLONE to copy;
11) Restart the physical standby in mount mode if it is running in Active Data Guard mode.
sqlplus / as sysdba select status from v$instance; -- ONLY if the current status is OPEN shutdown immediate; startup mount;
If the Standby is a RAC database, you should stop it using srvctl stop database command, since all instances needs to be restarted in MOUNT mode.
12) Enable recovery for the new PDB:
alter session set container=DB03A_CLONE; alter pluggable database enable recovery;
13) Enable the MRP again to sync the Standby applying the archived logs:
alter session set container=CDB$ROOT; ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
The steps 14-17 are optional, but I recommend to do it and confirm the new datafiles get ONLINE status in V$DATAFILE view.
14) Wait until Standby is sync with the Primary (apply lag = 0)
set linesize 300 col name format a25 col value format a25 col unit format a30 col time_computed format a20 select NAME, VALUE, UNIT, DATUM_TIME, TIME_COMPUTED FROM V$DATAGUARD_STATS;
15) Stop the MRP and open the standby and all the PDBs to synchronize the Standby controlfile status:
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL; alter database open; alter pluggable database all open;
16) Check datafile status
set pages 50 set lines 400 col name format a100 select con_id, file#, status, enabled, name from v$datafile order by 1,2;
17) Close the database and restart the MRP again
alter database close; ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
Nice to know about alert log messages
Case 1:
a) the standby alert log will show something like this when CREATE PDB is executed in Primary database.
Recovery created pluggable database DB03A_CLONE DB03A_CLONE(6):Tablespace-SYSTEM during PDB create skipped since source is in r/w mode or this is a refresh clone DB03A_CLONE(6):File #37 added to control file as 'UNNAMED00037'. Originally created as: DB03A_CLONE(6):'+DATA/CDBDG_A/2E065E6A74AD26A9E0630E01A8C03B9D/DATAFILE/system.377.1192959657' DB03A_CLONE(6):because the pluggable database was created with nostandby DB03A_CLONE(6):or the tablespace belonging to the pluggable database is
This is expected behavior until we restore the PDB with RMAN in the Standby.
Case 2:
The standby can log this in the alert log, just open the standby in READ-ONLY and close again.
WARNING: the control file may have incorrect data structure for some PDBs. Please open database and all pluggable databases read-only to synchronize the control file with the database dictionary. max_pdb is 7
Conclusion
In this blog post I covered all the steps to get a PDB properly cloned in a CDB with Data Guard configuration. As a final tip for it, if you Standby is a RAC database, I recommend you first shutdown all the instances using the SRVCTL, and following the blog steps only using SQLPLUS and RMAN. After you complete these steps, shutdown the local instance and start the database with SRVCTL again.