Oracle 19c RDBMS Migrate non cdb to cdb/pdb options 1.1

Note: These steps should be tested comprehensively and are undertaken at the users own risk

The non CDB architecture for Oracle will not be supported from Oracle 21c onwards, and should be considered when migrating to Oracle 19c.

The examples below will migrate a 19c non CDB database ‘PAUL01’ and plug it into a CDB named ‘SAMMY01’, the setup consists of 2 node RAC primary and 2 node RAC Dataguard standby. The standby database complicates this task but the 2 options to do this will be covered.

1.    References

Upgrade to 19c Virtual Classroom Series: Migrate to the Multitenant Architecture – Oracle Video Hub

Oracle Multitenant Administrator’s Guide, 19c

To CDB or not to CDB, that’s the question – A view on a Product Manager’s daily life (stepi.net)

https://mikedietrichde.com/

Reusing the Source Standby Database Files When Plugging a non-CDB as a PDB into the Primary Database of a Data Guard Configuration (Doc ID 2273304.1), read this for changes/patches/pre-requisites, at time of writing 3 pre-requisite patches needed

Making Use Deferred PDB Recovery and the STANDBYS=NONE Feature with Oracle Multitenant (Doc ID 1916648.1), read this for changes/patches/pre-requisites, at time of writing 3 pre-requisite patches needed

2.    Pre-requisites

  • Grid Infrastructure 19c installed ideally to latest support version/Release Update
  • RDBMS 19c s/w installed ideally to latest support version/Release Update
  • 19c Non CDB exists in Dataguard setup ready to migrate to CDB architecture
  • 19c CDB exists in Dataguard setup
  • Install latest version of tfactl/AHF, in case need to raise SR for help
  • Know where key logs are and how to collect logs needed for SR
  • Ensure application is compatible with 19c CDB architecture and know any required settings in advance

Steps below expect a CDB to exist in a Dataguard setup, ready for us to utilise to plug our non CDB into. I don’t intend to detail how to create and setup Dataguard, which should be standard DBA tasks. To create a CDB, the easiest way is to use dbca.

3.    MIGRATION to CBD options in a dataguard setup

As detailed by Roy, Mike and Daniel in their Multitenant Video (link in references), with an Oracle Dataguard setup there are 3 ways migrate and also ensure our dataguard standby database is preserved, but this requires manual action.

Options are:

  1. Reuse Standby datafiles
    1. Useful if migrating very large databases that would take days to recreate standby
    2. No duplication of files so twice space needed
    3. Minimal time without DR setup
    4. Useful if want to precreate CDB in advance
      1. Test backups, monitoring, site switch in advance
  • Defer PDB creation on the standby
    • Useful if want to preserve old standby files as these won’t be touched
    • Need to restore the PDB from Primary to Standby so more suited to smaller db’s
    • Useful if want to precreate CDB in advance
      • Test backups, monitoring, site switch in advance
  • Create/Recreate the Standby databases
    • Useful if Standby does not have any other PDB’s
    • Useful for smaller DB’s
    • Cleaner and less error prone as it’s a full restore which DBA’s may be more familiar with

We will walkthrough Options 1 and 2, Option 3 a full (re)create is a standard DBA task so will not be reviewed, as it is not any different to setting up dataguard or recreating a failed dataguard database.

Option 1 reuse datafiles on standby

Objective

To reinstate the standby database after the primary has been migrated from a non CDB to a CDB.

Reasons to reuse the standby datafiles

When migrating databases from a Non CDB to CBD architecture that are very large in size within a dataguard setup,the ability to reuse the standby CDB files as part of the migration could save hours/days of file copying and also reduces space needed by the process.

When we convert a Primary Non CDB to a PDB within a CDB that operation if we take no proactive action will break the standby.

Assumptions

We assume that the database to be migrated from a non CDB to a PDB in a CDB is already upgrading to the desired version.

We also assume the CDB that the non CDB will plug into already exist.

*database upgrades can easily be done using autoupgrade.jar

*A CDB can easily be created using dbca

Concepts

ASM Alias and GUID

Each database from 12c onwards is given a unique ID, called a GUID, in a CDB setup each PDB will have its own GUID.

The GUID is referenced by ASM when using Oracle Managed Files(OMF).

We can find a PDB or a non PDB GUID using the below SQL (as above source needs to be 12c or later)

select con_id, name, guid from v$containers;

When a datafile is created using a 12c or later CDB onwards using OMF the file location will be:

<OMF Location>/<DB UNIQUENAME>/<PDB GUID>/DATAFILE/<FILE_NAME> 
i.e.: +DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system_360_1078080281

When a PDB is plugged into the primary site, the recovery process on the standby site will try to find the datafile locations using the GUID format, the alert log will show something similar to:

Output on standby when pdb is plugged into primary:

PAUL01(3):Recovery scanning directory +DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE for any matching files

As our Non CDB standby datafiles are not using this format the scan the recovery process initiates fails and so the standby is compromised.

To allow the CDB to use the non CDB standby files we will trick Oracle into thinking the files are in GUID format by using ASM alias, then the recovery process on the standby will identify files and recovery will continue using:

ALTER DISKGROUP DATA add alias '<expected file location' for '<real file location';

As an example:

ALTER DISKGROUP DATA 
add alias '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/SYSAUX_359_1078080283' 
for '+DATA/PAUL01B/DATAFILE/SYSAUX.359.1078080283';

Dataguard and SCN

Oracle uses System Change Number (SCN) as an internal counter/clock to track changes, this mechanism also allows us to also check primary and standby databases are in sync, so if the Primary db is on a SCN 1234, and Standby db is on a SCN 1234 we know they are 100% in sync.

During the procedure to reuse datafiles it’s important that the databases for the primary and standby are on the exact same SCN which is part of the procedure detailed below.

process

Phase 1 Non CDB to CDB migration prep work

1) Generate ASM alias and run on the Standby ASM Instance

2) Stop Dataguard replication on the Non CDB databases

3) Synchronise Standby and Primary SCN’s manually

4) Stop Dataguard replication on the CDB databases

Phase 2 Non CDB to CDB migration

1) Create metadata XML manifest file with details to plug non CDB into CDB

2) Create pluggable database using the metadata XML file nocopy option

3) Convert the non-cdb to a PDB

Implementation Steps

Note down the GUID for the non CDB Database we are migrating (1 Minute)

On the on Primary non CDB node 1

. oraenv <<< PAUL01A1
sqlplus / as sysdba
col name for a12
select db_unique_name, database_role, cdb from v$database;
select guid from v$containers;
DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
PAUL01A 		       PRIMARY		NO

    CON_ID NAME 	GUID
---------- ------------ --------------------------------
	 0 PAUL01	C74107E1AD031A39E0536538A8C075C6

create a SQL Script (build_crt_alias_noncdb.sql) with following content (1 Minute)

On the on Standby non CDB node 1

save below into a file called: build_crt_alias_noncdb.sql

set newpage 0
set linesize 999
set pagesize 0
set feedback off
set heading off
set echo off
set space 0
set tab off
set trimspool on
set ver off
spool crt_noncdb_alias.sql
prompt set echo on
select 'ALTER DISKGROUP &&diskgrp_name_without_plus_sign add directory '||''''||'+&&diskgrp_name_without_plus_sign/&&new_stby_name_in_upper_case/'||guid||''''||';' from v$containers;
select 'ALTER DISKGROUP &&diskgrp_name_without_plus_sign add directory '||''''||'+&&diskgrp_name_without_plus_sign/&&new_stby_name_in_upper_case/'||guid||'/DATAFILE'||''''||';' from v$containers;
select 'ALTER DISKGROUP &&diskgrp_name_without_plus_sign add alias '||''''||replace(replace(replace(upper_dfname,'.','_'),'/&old_stby_name_in_upper_case/','/&&new_stby_name_in_upper_case/'),'DATAFILE',guid||'/DATAFILE')||''''||' for '||''''||upper_dfname||''''||';' from (select upper(name) upper_dfname from v$datafile) df, (select guid from v$containers) con;
exit

run the script: build_crt_alias_noncdb.sql (1 Minute)

The script will request, Diskgroup, old and new standby db unique names: example below:

Enter value for diskgrp_name_without_plus_sign: <Diskgroup name>		: DATA
Enter value for new_stby_name_in_upper_case: <CDB STANDBY DB UNIQUE NAME>	: SAMMY01B
Enter value for old_stby_name_in_upper_case: <NON CDB STANDBY DB UNIQUE NAME>   : PAUL01B

In the output check the GUID we found earlier (C74107E1AD031A39E0536538A8C075C6) matches

. oraenv <<< PAUL01B1
sqlplus / as sysdba
select db_unique_name, database_role, cdb from v$database;
DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
PAUL01B 		       PHYSICAL STANDBY NO
@build_crt_alias_noncdb.sql

This will create a script called: crt_noncdb_alias.sql

cat crt_noncdb_alias.sql:
set echo on
Enter value for diskgrp_name_without_plus_sign: DATA
Enter value for new_stby_name_in_upper_case: SAMMY01B
ALTER DISKGROUP DATA add directory '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6';
ALTER DISKGROUP DATA add directory '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE';
Enter value for old_stby_name_in_upper_case: PAUL01B
ALTER DISKGROUP DATA add alias '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/SYSTEM_360_1078080281' for '+DATA/PAUL01B/DATAFILE/SYSTEM.360.1078080281';
ALTER DISKGROUP DATA add alias '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/SYSAUX_359_1078080283' for '+DATA/PAUL01B/DATAFILE/SYSAUX.359.1078080283';
ALTER DISKGROUP DATA add alias '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/UNDOTBS1_358_1078080307' for '+DATA/PAUL01B/DATAFILE/UNDOTBS1.358.1078080307';
ALTER DISKGROUP DATA add alias '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/UNDOTBS2_357_1078080309' for '+DATA/PAUL01B/DATAFILE/UNDOTBS2.357.1078080309';

In the above script if not using LOCAL undo feature on the CDB then remove the UNDO files from the script, if not sure check on CDB:

. oraenv <<< SAMMY01A1
sqlplus / as sysdba
col PROPERTY_NAME for a20
col PROPERTY_VALUE for a20 
select property_name, property_value from   database_properties where  property_name = 'LOCAL_UNDO_ENABLED';

PROPERTY_NAME	     PROPERTY_VALUE
-------------------- --------------------
LOCAL_UNDO_ENABLED   TRUE

We are using local undo so will leave script as is.

run crt_noncdb_alias.sql on ASM instance on Standy site (1 Minute)

ps -ef|grep ora_smon 

check you are on standby site

oracle   14749     1  0 13:19 ?        00:00:00 ora_smon_SAMMY01B1

oracle   15923     1  0 13:20 ?        00:00:00 ora_smon_PAUL01B1

. oraenv <<< +ASM1
sqlplus / as sysasm
show user
select instance_name from v$instance;

USER is "SYS"

INSTANCE_NAME
----------------
+ASM1

Run alias script ignore the SP2-0734 errors from non sql text in the script:

@crt_noncdb_alias.sql
SQL> @crt_noncdb_alias.sql
SQL> Enter value for diskgrp_name_without_plus_sign: DATA
SP2-0734: unknown command beginning "Enter valu..." - rest of line ignored.
SQL> Enter value for new_stby_name_in_upper_case: SAMMY01B
SP2-0734: unknown command beginning "Enter valu..." - rest of line ignored.
SQL> ALTER DISKGROUP DATA add directory '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6';

Diskgroup altered.

SQL> ALTER DISKGROUP DATA add directory '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE';

Diskgroup altered.

SQL> Enter value for old_stby_name_in_upper_case: PAUL01B
SP2-0734: unknown command beginning "Enter valu..." - rest of line ignored.
SQL> ALTER DISKGROUP DATA add alias '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/SYSTEM_360_1078080281' for '+DATA/PAUL01B/DATAFILE/SYSTEM.360.1078080281';

Diskgroup altered.

SQL> ALTER DISKGROUP DATA add alias '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/SYSAUX_359_1078080283' for '+DATA/PAUL01B/DATAFILE/SYSAUX.359.1078080283';

Diskgroup altered.

SQL> ALTER DISKGROUP DATA add alias '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/UNDOTBS1_358_1078080307' for '+DATA/PAUL01B/DATAFILE/UNDOTBS1.358.1078080307';

Diskgroup altered.

SQL> ALTER DISKGROUP DATA add alias '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/UNDOTBS2_357_1078080309' for '+DATA/PAUL01B/DATAFILE/UNDOTBS2.357.1078080309';

Diskgroup altered.

*Note any issues with wrong alias that need to be removed used rmalias command (NOT rm which will remove the actual file!)

 Stop replication on the on Standby non CDB node 1 (5 Minutes)

. oraenv <<< PAUL01B1
dgmgrl /
show configuration;
show database 'PAUL01B';
edit database 'PAUL01B' set state='apply-off';

Create GRP on Standby CDB node 1 (5 Minutes)

. oraenv <<< SAMMY01B1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE from v$database;
alter database recover managed standby database cancel;
create restore point pre_plugin_standby guarantee flashback database;
recover managed standby database disconnect using current logfile;

The GRP on the CDB standby database only purpose is to allow the ability to restart the ASM directory search operation on the CDB standby database to find the aliases. If an issue with PDB plugin and alias setup, we could flashback CDB standby DB to restore point, fix alias issue then re-enable apply to see if issue resolved

DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
SAMMY01B		       PHYSICAL STANDBY YES

SQL> alter database recover managed standby database cancel;

Database altered.

SQL> create restore point pre_plugin_standby guarantee flashback database;

Restore point created.

SQL> recover managed standby database disconnect using current logfile;
Media recovery complete.

Shutdown the non-CDB primary cleanly, then restart one instance in mount mode. on Primary non CDB node 1 (5 Minutes)

*If primary is mutli instance RAC database, shut down all the other instances and continue on one instance only

. oraenv <<< PAUL01A1
srvctl stop database -db PAUL01A
srvctl status database -db PAUL01A
Instance PAUL01A1 is not running on node rac01-a
Instance PAUL01A2 is not running on node rac02-a

Startup mount Primary on a single:

sqlplus / as sysdba
startup mount
select DB_UNIQUE_NAME, DATABASE_ROLE, open_mode, CDB from v$database;
DB_UNIQUE_NAME		       DATABASE_ROLE	OPEN_MODE	     CDB
------------------------------ ---------------- -------------------- ---
PAUL01A 		       PRIMARY		MOUNTED 	     NO

flush the redo to the standby site on Primary non CDB node 1 (1 Minute)

(update Standby db unique name in command)

select DB_UNIQUE_NAME, DATABASE_ROLE, open_mode, CDB from v$database;
alter system flush redo to PAUL01B no confirm apply;
DB_UNIQUE_NAME		       DATABASE_ROLE	OPEN_MODE	     CDB
------------------------------ ---------------- -------------------- ---
PAUL01A 		       PRIMARY		MOUNTED 	     NO

System altered.

open the database read-only (will not apply redo as we stopped the redo-apply) on Primary non CDB node 1 (1 Minute)

select DB_UNIQUE_NAME, DATABASE_ROLE, open_mode, CDB from v$database;
alter database open read only;
select DB_UNIQUE_NAME, DATABASE_ROLE, open_mode, CDB from v$database;
DB_UNIQUE_NAME		       DATABASE_ROLE	OPEN_MODE	     CDB
------------------------------ ---------------- -------------------- ---
PAUL01A 		       PRIMARY		MOUNTED 	     NO

Database altered.

DB_UNIQUE_NAME		       DATABASE_ROLE	OPEN_MODE	     CDB
------------------------------ ---------------- -------------------- ---
PAUL01A 		       PRIMARY		READ ONLY	     NO

determine the checkpoint_change number on Primary non CDB node 1 (1 Minute)

select DB_UNIQUE_NAME, DATABASE_ROLE, open_mode, CDB from v$database;
select file#, CHECKPOINT_CHANGE# from v$datafile_header where file#=1;
DB_UNIQUE_NAME		       DATABASE_ROLE	OPEN_MODE	     CDB
------------------------------ ---------------- -------------------- ---
PAUL01A 		       PRIMARY		READ ONLY	     NO

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
	 1	      4003245

recover the standby database until this number on Standby non CDB node 1 (5 Minutes)

Using: alter database recover managed standby database until change <SCN Above>;

We need to recover standby db to same SCN as the primary: from above 4003245

. oraenv <<< PAUL01B1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
PAUL01B 		       PHYSICAL STANDBY NO
alter database recover managed standby database until change 4003245;
Database altered.

validate the files on the source non-CDB standby are consistent with the files from the non-CDB primary. on Standby non CDB node 1 (1 Minute)

. oraenv <<< PAUL01B1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
select file#, CHECKPOINT_CHANGE# from v$datafile_header where file#=1;
DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
PAUL01B 		       PHYSICAL STANDBY NO

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
	 1	      4003245 ------> Good It’s the same!

Create manifest file need to plug non CDB into CDB on Primary non CDB node 1 (5 Minutes)

. oraenv <<< PAUL01A1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE,CDB from v$database;
set serveroutput on
exec dbms_pdb.describe('/var/tmp/PAUL01A.xml');
!ls -lrt /var/tmp/PAUL01A.xml	
!head -10 /var/tmp/PAUL01A.xml
DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
PAUL01A 		       PRIMARY		NO

SQL> set serveroutput on
exec dbms_pdb.describe('/var/tmp/PAUL01A.xml');

PL/SQL procedure successfully completed.

-rw-r--r-- 1 oracle asmadmin 7226 Jul 24 18:55 /var/tmp/PAUL01A.xml

SQL> <?xml version="1.0" encoding="UTF-8"?>
<PDB>
  <xmlversion>1</xmlversion>
  <pdbname>PAUL01</pdbname>
  <cid>0</cid>
  <byteorder>1</byteorder>
  <vsn>318767104</vsn>
  <vsns>
    <vsnnum>19.0.0.0.0</vsnnum>
    <cdbcompt>12.1.0.0.0</cdbcompt>

Primary and Standby non CDB databases standby management check and stop (5 Minutes)

a) on Primary non CDB node 1 stop database

. oraenv <<< PAUL01A1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE from gv$database;
shutdown immediate;
exit
srvctl status database -d PAUL01A
Instance PAUL01A1 is not running on node rac01-a
Instance PAUL01A2 is not running on node rac02-a

b) on Standby non CDB node 1 Stop database                                                                                                                         

. oraenv <<< PAUL01B1
srvctl stop database -d PAUL01B
srvctl status database -d PAUL01B
Instance PAUL01B1 is not running on node rac01-b
Instance PAUL01B2 is not running on node rac02-b

Check standby_file_management is AUTO on Primary and Standby CDB

— Check standby_file_management parameter is AUTO

. oraenv <<< SAMMY01A1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
show parameter standby_file_management
alter system set standby_file_management='AUTO' scope=both;
. oraenv <<< SAMMY01B1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
show parameter standby_file_management
alter system set standby_file_management='AUTO' scope=both;
			DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
SAMMY01A		       PRIMARY		YES

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
standby_file_management 	     string	 AUTO

DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
SAMMY01B		       PHYSICAL STANDBY YES

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
standby_file_management 	     string	 AUTO
 

plug in non CD on Primary CDB node 1 (5 Minutes)

Using the xml manifest we generated earlier ‘/var/tmp/PAUL01A.xml’, we will now plug the non cdb database into our CDB, we give our PDB the same name as out non PDB PAUL01.

a) plugin on Primary CDB node 1

. oraenv <<< SAMMY01A1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
SAMMY01A		       PRIMARY		YES
!ls -lrt /var/tmp/PAUL01A.xml
create pluggable database PAUL01 using '/var/tmp/PAUL01A.xml' tempfile reuse nocopy;
show pdbs
create pluggable database PAUL01 using '/var/tmp/PAUL01A.xml' tempfile reuse nocopy;
Pluggable database created.
show pdbs

     CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  READ ONLY  NO
	 3 PAUL01			  MOUNTED

check on Standby CDB node 1 (5 Minutes)

If we check the alertlog on the Standby CDB, we should see that the non CDB files which have a ASM Alias in place have been discovered by the recovery process and also the PDB has been added to the Standby CDB.

. oraenv <<< SAMMY01B1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
show pdbs

DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
SAMMY01B		       PHYSICAL STANDBY YES

SQL> 
    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  MOUNTED
	 3 PAUL01			  MOUNTED
tail -50 /u01/app/oracle/diag/rdbms/sammy01b/SAMMY01B1/trace/alert_SAMMY01B1.log
Recovery created pluggable database PAUL01
PAUL01(3):Recovery scanning directory +DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE for any matching files
PAUL01(3):Datafile 9 added to flashback set
PAUL01(3):Successfully added datafile 9 to media recovery
PAUL01(3):Datafile #9: '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system_360_1078080281'
PAUL01(3):Datafile 10 added to flashback set
PAUL01(3):Successfully added datafile 10 to media recovery
PAUL01(3):Datafile #10: '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux_359_1078080283'
PAUL01(3):Datafile 11 added to flashback set
PAUL01(3):Successfully added datafile 11 to media recovery
PAUL01(3):Datafile #11: '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1_358_1078080307'
PAUL01(3):Datafile 12 added to flashback set
PAUL01(3):Successfully added datafile 12 to media recovery
PAUL01(3):Datafile #12: '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2_357_1078080309'

convert the non-cdb to a PDB (noncdb_to_pdb.sql) on Primary CDB node 1 (60 Minutes)

  • Set and check env
cd /var/tmp
. oraenv <<< SAMMY01A1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
show pdbs
DATABASE_ROLE	CDB
------------------------------ ---------------- ---
SAMMY01A		       PRIMARY		YES

SQL> 
    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  READ ONLY  NO
	 3 PAUL01			  MOUNTED

  • Change session to new PDB
alter session set container = PAUL01;
show con_name
Session altered.

CON_NAME
------------------------------
PAUL01
  • run noncdb to pdb conversion script (rerunnable since version 12.2)
spool noncdb_to_pdb.log
@?/rdbms/admin/noncdb_to_pdb.sql
spool off

Script may take some time to run can monitor log for progress in /var/tmp/noncdb_to_pdb.log

Also grep for errors once complete

grep ^ORA- noncdb_to_pdb.log

Post checks  (10 Minutes)

a) After the process has completed, verify there are no errors or the standby database is in sync

review primary alertlogs:

/u01/app/oracle/diag/rdbms/sammy01a/SAMMY01A1/trace/alert_SAMMY01A1.log

/u01/app/oracle/diag/rdbms/sammy01a/SAMMY01A2/trace/alert_SAMMY01A2.log

review standby alertslogs:

/u01/app/oracle/diag/rdbms/sammy01b/SAMMY01B1/trace/alert_SAMMY01B1.log /u01/app/oracle/diag/rdbms/sammy01b/SAMMY01B2/trace/alert_SAMMY01B2.log

b) dataguard check

. oraenv <<< SAMMY01A1
dgmgrl /
show configuration;
show database 'SAMMY01B';
DGMGRL> show configuration;

Configuration - SAMMY01

  Protection Mode: MaxAvailability
  Members:
  SAMMY01A - Primary database
    SAMMY01B - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 15 seconds ago)

DGMGRL> show database 'SAMMY01B';

Database - SAMMY01B

  Role:               PHYSICAL STANDBY
  Intended State:     APPLY-ON
  Transport Lag:      0 seconds (computed 1 second ago)
  Apply Lag:          0 seconds (computed 1 second ago)
  Average Apply Rate: 428.00 KByte/s
  Real Time Query:    OFF
  Instance(s):
    SAMMY01B1 (apply instance)
    SAMMY01B2

Database Status:
SUCCESS

sql based checks (5 Minutes)

a) Datafile check on primary

. oraenv <<< SAMMY01A1
sqlplus / as sysdba
set lines 200
set pages 1000
col name for a90
select name, status from v$datafile order by con_id, file#;
NAME										    STATUS
------------------------------------------------------------------------------------------ -------
+DATA/SAMMY01A/DATAFILE/system.431.1078081555					    SYSTEM
+DATA/SAMMY01A/DATAFILE/sysaux.433.1078081565					    ONLINE
+DATA/SAMMY01A/DATAFILE/undotbs1.435.1078081569 					    ONLINE
+DATA/SAMMY01A/DATAFILE/undotbs2.410.1078081615 					    ONLINE
+DATA/SAMMY01A/DATAFILE/users.409.1078081615					    ONLINE
+DATA/SAMMY01A/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/system.432.1078081557	    SYSTEM
+DATA/SAMMY01A/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/sysaux.434.1078081567	    ONLINE
+DATA/SAMMY01A/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/undotbs1.436.1078081571	    ONLINE
+DATA/PAUL01A/DATAFILE/system.383.1078075503					    SYSTEM
+DATA/PAUL01A/DATAFILE/sysaux.384.1078075509						    ONLINE
+DATA/PAUL01A/DATAFILE/undotbs1.385.1078075511					    ONLINE
+DATA/PAUL01A/DATAFILE/undotbs2.390.1078077741					    ONLINE

standby:
. oraenv <<< SAMMY01B1
sqlplus / as sysdba
set lines 200
set pages 1000
col name for a90
select name, status from v$datafile order by con_id, file#;
NAME										   STATUS
------------------------------------------------------------------------------------------ -------
+DATA/SAMMY01B/DATAFILE/system.450.1078092817					   SYSTEM
+DATA/SAMMY01B/DATAFILE/sysaux.452.1078092833					   ONLINE
+DATA/SAMMY01B/DATAFILE/undotbs1.454.1078092845 					   ONLINE
+DATA/SAMMY01B/DATAFILE/undotbs2.456.1078092853 					   ONLINE
+DATA/SAMMY01B/DATAFILE/users.457.1078092855					   ONLINE
+DATA/SAMMY01B/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/system.451.1078092819	   SYSTEM
+DATA/SAMMY01B/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/sysaux.453.1078092837                 ONLINE
+DATA/SAMMY01B/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/undotbs1.455.1078092845	   ONLINE
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system_360_1078080281	   SYSTEM
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux_359_1078080283	   ONLINE
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1_358_1078080307	   ONLINE
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2_357_1078080309	   ONLINE

open PDB  on Primary CDB node 1 (5 Minutes)

. oraenv <<< SAMMY01A1
sqlplus / as sysdba
col name for a20
select name, open_mode from v$pdbs;
NAME		     OPEN_MODE
-------------------- ----------
PDB$SEED	     READ ONLY
PAUL01		     MOUNTED
alter pluggable database PAUL01 open;
select con_id, type, message, status from PDB_PLUG_IN_VIOLATIONS where status<>'RESOLVED' order by time;
select name, open_mode from v$pdbs;
Pluggable database altered.

no rows selected

NAME		     OPEN_MODE
-------------------- ----------
PDB$SEED	     READ ONLY
PAUL01		     READ WRITE

add a data file to the temp tablespace of the newly plugged in PDB (5 Minutes)

Can only do if pdb is opened on so after a switchover

alter session set container = PAUL01;
alter tablespace temp add tempfile '+DATA' size <size>M;

Add services to Grid Infrastructure as required on PRIMARY and STANDBY (5 Minute)

srvctl add service -d cdbname -s service_name -pdb pdbname

Backup the new PDB (5 to x Minutes depending on size)

connect to CDB

backup database plus archivelog;

drop restore point on the Standby CDB (5 Minutes)

. oraenv <<< SAMMY01B1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
drop restore point pre_plugin_standby;

perform a site switch to the standby and back to the Primary to ensure all is working as expected after implementing (30 Minutes)

Will not document as standard dataguard switchover commands.

Option 2 DEFER PDB creation on the standby

Objective

To reinstate the standby database after the primary has been migrated from a non CDB to a CDB.

Reasons to DEFER STANDBY PDB creation

Normally when plugging a PDB into a Primary database, the standby DB will not replicate the operation and will be in a state of inconsistency as the file locations for the new PDB would not be visible to the standby instance.

Using the deferred method, allows us to delay standby creation of PDB into an existing Standby CDB that may cater for other PDBs already, this allows the standby to function and allows us to choose when we are ready to copy over the new PDB just added on the Primary site once we are happy with the primary site.

When we convert a Primary Non CDB to a PDB within a CDB that operation if we take no proactive action will break the standby.

Assumptions

We assume that the database to be migrated from a non CDB to a PDB in a CDB is already upgrading to the desired version.

We also assume the CDB that the non CDB will plug into already exist.

*database upgrades can easily be done using autoupgrade.jar

*A CDB can easily be created using dbca

Concepts

STANDBYS=NONE clause

In Oracle version 12.1.0.2, the CREATE PLUGGABLE DATABASE statement has a new clause, STANDBYS=NONE, this defers creation of the standby PDB being plugged in, while allowing pre-existing PDB’s in the standby CDB to be unaffected.

The metadata for the PDB is still created in the standby CDB, but its datafiles are marked OFFLINE.

Implementation Steps

Create manifest file need to plug non CDB into CDB on Primary non CDB node 1 (5 Minutes)

. oraenv <<< PAUL01A1
srvctl stop database -d PAUL01A
srvctl status database -d PAUL01A
Instance PAUL01A1 is not running on node rac01-a
Instance PAUL01A2 is not running on node rac02-a
sqlplus / as sysdba
startup OPEN READ ONLY;
select DB_UNIQUE_NAME, DATABASE_ROLE,CDB from v$database;
DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
PAUL01A 		       PRIMARY		NO
set serveroutput on
exec dbms_pdb.describe('/var/tmp/PAUL01A.xml');
!ls -lrt /var/tmp/PAUL01A.xml
!head -10 /var/tmp/PAUL01A.xml
shutdown immediate
exit
PL/SQL procedure successfully completed.

SQL>!ls -lrt /var/tmp/PAUL01A.xml
-rw-r--r-- 1 oracle asmadmin 7205 Jul 25 00:51 /var/tmp/PAUL01A.xml

SQL>!head -10 /var/tmp/PAUL01A.xml
-rw-r--r-- 1 oracle asmadmin 7205 Jul 25 00:51 /var/tmp/PAUL01A.xml

SQL> <?xml version="1.0" encoding="UTF-8"?>
<PDB>
  <xmlversion>1</xmlversion>
  <pdbname>PAUL01</pdbname>
  <cid>0</cid>
  <byteorder>1</byteorder>
  <vsn>318767104</vsn>
  <vsns>
    <vsnnum>19.0.0.0.0</vsnnum>
    <cdbcompt>12.1.0.0.0</cdbcompt>

stop and disable Standby non CDB databases (5 Minutes)

Stop Standby non CDB node 1

. oraenv <<< PAUL01B1
srvctl stop database -d PAUL01B
srvctl status database -d PAUL01B
Instance PAUL01B1 is not running on node rac01-b
Instance PAUL01B2 is not running on node rac02-b
srvctl disable database -d PAUL01B

plug in non CD on Primary CDB node 1 (5 Minutes)

. oraenv <<< SAMMY01A1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
SAMMY01A		       PRIMARY		YES
!ls -lrt /var/tmp/PAUL01A.xml

Using the STANDBY=NONE syntax, plug the non cdb into the CBD using below syntax

create pluggable database <PDBNAME> using ‘<manifest file>’ tempfile reuse nocopy STANDBYS=NONE;

create pluggable database PAUL01 using '/var/tmp/PAUL01A.xml' tempfile reuse nocopy STANDBYS=NONE;
show pdbs
Pluggable database created.

SQL> show pdbs

    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  READ ONLY  NO
	 3 PAUL01	

convert the non-cdb to a PDB (noncdb_to_pdb.sql) on Primary CDB node 1 (60 Minutes)

cd /var/tmp
. oraenv <<< SAMMY01A1
sqlplus / as sysdba
select DB_UNIQUE_NAME, DATABASE_ROLE, CDB from v$database;
alter session set container = PAUL01;
show con_name


    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  READ ONLY  NO
	 3 PAUL01			  MOUNTED

Session altered.

CON_NAME
------------------------------
PAUL01

-- rerunnable since 12.2
spool noncdb_to_pdb.log
@?/rdbms/admin/noncdb_to_pdb.sql
spool off

Script may take some time to run can monitor log for progress in /var/tmp/noncdb_to_pdb.log

Also grep for errors once complete

grep ^ORA- noncdb_to_pdb.log

open the new PDB on the primary (5 Minutes)

. oraenv <<< SAMMY01A1
sqlplus / as sysdba
col name for a20
select name, open_mode from v$pdbs;
NAME		     OPEN_MODE
-------------------- ----------
PDB$SEED	     READ ONLY
PAUL01		     MOUNTED
alter pluggable database PAUL01 open;
select con_id, type, message, status from PDB_PLUG_IN_VIOLATIONS where status<>'RESOLVED' order by time;
select name, open_mode from v$pdbs;
Pluggable database altered.

no rows selected

NAME		     OPEN_MODE
-------------------- ----------
PDB$SEED	     READ ONLY
PAUL01		     READ WRITE

Current progress of migration (10 Minutes)

After the PDB creation has completed on the primary database, the redo for the creation of the metadata only will be applied on the standby database. What this means is no data will exist for the pdb but the standby will know the pdb exists but datafiles do not exist.

The standby database will show the PDB has been created but V$PDBS will show that it has a RECOVERY_STATUS of disabled.

The SYSTEM tablespace will be SYSOFF to identify the file as a SYSTEM tablespace datafile and offline. 

As we expect we will not be able to open the PDB on the standby database as it has no files to access.

The alert log for the creation of the PDB will note that the PDB was created with the STANDBYS=NONE clause (identified as “nostandby”) and state the tablespace was created in a state of OFFLINE.

. oraenv <<< SAMMY01B1
sqlplus / as sysdba
show pdbs
col name for a32
select name, recovery_status from v$pdbs;
alter session set container=PAUL01
CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  MOUNTED
	 3 PAUL01			  MOUNTED
SQL> alter session set container=PAUL01;

Session altered.

Check status of datafiles:
set lines 120           
set pages 9999
col name format a65
col error for a40

select name, status from v$datafile;
NAME								  STATUS
----------------------------------------------------------------- -------
/u01/app/oracle/product/19.6.0/db_1/dbs/UNNAMED00013		  SYSOFF
/u01/app/oracle/product/19.6.0/db_1/dbs/UNNAMED00014		  RECOVER
/u01/app/oracle/product/19.6.0/db_1/dbs/UNNAMED00015		  RECOVER
/u01/app/oracle/product/19.6.0/db_1/dbs/UNNAMED00016		  RECOVER
select * from v$recover_file;
FILE# ONLINE  ONLINE_ ERROR				       CHANGE# TIME	     CON_ID
---------- ------- ------- ---------------------------------------- ---------- --------- -----
	13 OFFLINE OFFLINE FILE MISSING 				     0			  3
	14 OFFLINE OFFLINE FILE MISSING 				     0			  3
	15 OFFLINE OFFLINE FILE MISSING 				     0			  3
	16 OFFLINE OFFLINE FILE MISSING 				     0			  3
col name for a32
select name, recovery_status from v$pdbs;
NAME				 RECOVERY
-------------------------------- --------
PAUL01				 DISABLED


standby alertlog:
tail -100 /u01/app/oracle/diag/rdbms/sammy01b/SAMMY01B1/trace/alert_SAMMY01B1.log
Recovery created pluggable database PAUL01
PAUL01(3):File #13 added to control file as 'UNNAMED00013'. Originally creat
PAUL01(3):'+DATA/PAUL01A/DATAFILE/system.440.1078783883'
PAUL01(3):because the pluggable database was created with nostandby
PAUL01(3):or the tablespace belonging to the pluggable database is
PAUL01(3):offline.
PAUL01(3):File #14 added to control file as 'UNNAMED00014'. Originally created as:
PAUL01(3):'+DATA/PAUL01A/DATAFILE/sysaux.414.1078783883'
PAUL01(3):because the pluggable database was created with nostandby
PAUL01(3):or the tablespace belonging to the pluggable database is
PAUL01(3):offline.
PAUL01(3):File #15 added to control file as 'UNNAMED00015'. Originally created as:
PAUL01(3):'+DATA/PAUL01A/DATAFILE/undotbs1.441.1078783885'
PAUL01(3):because the pluggable database was created with nostandby
PAUL01(3):or the tablespace belonging to the pluggable database is
PAUL01(3):offline.
PAUL01(3):File #16 added to control file as 'UNNAMED00016'. Originally created as:
PAUL01(3):'+DATA/PAUL01A/DATAFILE/undotbs2.416.1078783883'
PAUL01(3):because the pluggable database was created with nostandby
PAUL01(3):or the tablespace belonging to the pluggable database is
PAUL01(3):offline.
2021-07-25T01:07:37.030515+01:00
PR00 (PID:22741): Media Recovery Waiting for T-1.S-41 (in transit)
2021-07-25T01:07:37.062511+01:00..

Check status of dataguard (5 Minutes)

Oracle will periodically runs analysis of the databases in a Data Guard configuration (also occur after a instance bounce).

After this analysis we may see additional information as part of the Data Guard broker VALIDATE DATABASE command.

dgmgrl /
show configuration;
show database 'SAMMY01B';
validate database 'SAMMY01B';
DGMGRL for Linux: Release 19.0.0.0.0 - Production on Sun Jul 25 01:30:53 2021
Version 19.6.0.0.0

Copyright (c) 1982, 2019, Oracle and/or its affiliates.  All rights reserved.

Welcome to DGMGRL, type "help" for information.
Connected to "SAMMY01B"
Connected as SYSDG.
DGMGRL> show configuration;

Configuration - SAMMY01

  Protection Mode: MaxAvailability
  Members:
  SAMMY01A - Primary database
    SAMMY01B - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 27 seconds ago)


DGMGRL> show database 'SAMMY01B';

Database - SAMMY01B

  Role:               PHYSICAL STANDBY
  Intended State:     APPLY-ON
  Transport Lag:      0 seconds (computed 1 second ago)
  Apply Lag:          0 seconds (computed 1 second ago)
  Average Apply Rate: 146.00 KByte/s
  Real Time Query:    OFF
  Instance(s):
    SAMMY01B1 (apply instance)
    SAMMY01B2

Database Status:
SUCCESS

DGMGRL> validate database 'SAMMY01B';

  Database Role:     Physical standby database
  Primary Database:  SAMMY01A

  Ready for Switchover:  Yes
  Ready for Failover:    Yes (Primary Running)

  Managed by Clusterware:
    SAMMY01A:  YES            
    SAMMY01B:  YES            

  Temporary Tablespace File Information:
    SAMMY01A TEMP Files:  3
    SAMMY01B TEMP Files:  2

  Log Files Cleared:
    SAMMY01A Standby Redo Log Files:  Cleared
    SAMMY01B Online Redo Log Files:   Not Cleared
    SAMMY01B Standby Redo Log Files:  Available
 

Drop old standby db to free space (OPTIONAL) (10 Minutes)

At this point ‘if’ we need to free space used by old standby non cdb for its PDB replacement, we may have to drop that database.

. oraenv <<< PAUL01B1
sqlplus / as sysdba
startup nomount
select instance_name from v$instance;
alter system set cluster_database=FALSE scope=spfile;
INSTANCE_NAME
----------------
PAUL01B1

System altered.
shutdown immediate;
startup mount exclusive;
select db_unique_name, database_role, cdb from v$database;
DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
PAUL01B 		       PHYSICAL STANDBY NO

Review output above make sure on correct database we will DROP as not easy return.
alter system enable restricted session;
drop database;

System altered.

Database dropped.

We May need to clean up FRA and some files manually in ASM.

Using RMAN for copying the files from the primary PDB to standby (10 to x Minutes depending on size)

If there is a strict archive log deletion policy like APPLIED ON ALL STANDBY, change this to avoid deletion of archices that may be needed for the standby PDB build

. oraenv <<< SAMMY01A1
rman target /
show archivelog deletion policy;
configure archivelog deletion policy to none;

RMAN configuration parameters for database with db_unique_name SAMMY01A are:
CONFIGURE ARCHIVELOG DELETION POLICY TO NONE; # default

Verify that the Primary PDB is open for access on the primary database:

select db_unique_name, database_role, cdb from v$database;
show pdbs

DB_UNIQUE_NAME		       DATABASE_ROLE	CDB
------------------------------ ---------------- ---
SAMMY01A		       PRIMARY		YES

    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  READ ONLY  NO
	 3 PAUL01			  READ WRITE NO

c) prepare rman script to restore PDB on standby CDB and run

. oraenv <<< SAMMY01B1
rman target /
run {
set newname for pluggable database PAUL01 to new;
restore pluggable database PAUL01 from service ' SAMMY01A';
}

executing command: SET NEWNAME

Starting restore at 25-JUL-21
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=24 instance=SAMMY01B1 device type=DISK
allocated channel: ORA_DISK_2
channel ORA_DISK_2: SID=261 instance=SAMMY01B1 device type=DISK

channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: using network backup set from service  SAMMY01A
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00013 to +DATA
channel ORA_DISK_2: starting datafile backup set restore
channel ORA_DISK_2: using network backup set from service  SAMMY01A
channel ORA_DISK_2: specifying datafile(s) to restore from backup set
channel ORA_DISK_2: restoring datafile 00014 to +DATA
channel ORA_DISK_2: restore complete, elapsed time: 00:00:16
channel ORA_DISK_2: starting datafile backup set restore
channel ORA_DISK_2: using network backup set from service  SAMMY01A
channel ORA_DISK_2: specifying datafile(s) to restore from backup set
channel ORA_DISK_2: restoring datafile 00015 to +DATA
channel ORA_DISK_1: restore complete, elapsed time: 00:00:23
channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: using network backup set from service  SAMMY01A
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00016 to +DATA
channel ORA_DISK_2: restore complete, elapsed time: 00:00:07
channel ORA_DISK_1: restore complete, elapsed time: 00:00:03
Finished restore at 25-JUL-21

STARTUP MOUNT STANDBY and DISABLE redo apply (10 Minutes)

The standby database is going to be restarted in mount mode, but it must not have redo apply running.

Connect using dgmgrl and disable redo apply for the standby database.

. oraenv <<< SAMMY01B1
dgmgrl /
show configuration
edit database 'SAMMY01B' set state='apply-off';
exit

DGMGRL> show configuration

Configuration - SAMMY01

  Protection Mode: MaxAvailability
  Members:
  SAMMY01A - Primary database
    SAMMY01B - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 13 seconds ago)

DGMGRL> edit database 'SAMMY01B' set state='apply-off';
Succeeded.

Connect to RMAN on standby database and switch the PDB files to the ones restored (5 Minutes)

. oraenv <<< SAMMY01B1
rman target /
switch pluggable database PAUL01 to copy;

output:
connected to target database: SAMMY01 (DBID=2878419394, not open)

RMAN> switch pluggable database PAUL01 to copy;

using target database control file instead of recovery catalog
datafile 13 switched to datafile copy "+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system.350.1078796917"
datafile 14 switched to datafile copy "+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux.361.1078796917"
datafile 15 switched to datafile copy "+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1.482.1078796933"
datafile 16 switched to datafile copy "+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2.483.1078796939"

Oracle 18c and later create online file script ON STANDBY (do not run yet) (1 Minutes)

cd /var/tmp
. oraenv <<< SAMMY01B1
sqlplus / as sysdba
show pdbs
alter session set container=PAUL01;
set lines 120
set pages 9999
spool online_files.sql
select 'alter database datafile '||''''||name||''''||' online;' from v$datafile;
spool off


    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  MOUNTED
	 3 PAUL01			  MOUNTED

Session altered.


SQL> alter session set container=PAUL01;
set lines 120
set pages 9999
Session altered.


'ALTERDATABASEDATAFILE'||''''||NAME||''''||'ONLINE;'
------------------------------------------------------------------------------------------------------------------------
alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system.350.1078796917' online;
alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux.361.1078796917' online;
alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1.482.1078796933' online;
alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2.483.1078796939' online;

* ADG would need to be disable if using now

Issue the ENABLE RECOVERY command (5 Minutes)

. oraenv <<< SAMMY01B1
sqlplus / as sysdba
alter session set container=PAUL01;
alter pluggable database enable recovery;
Session altered.

Pluggable database altered.

Oracle 18c and later run the datafile online script (5 Minutes)

cd /var/tmp
. oraenv <<< SAMMY01B1
sqlplus / as sysdba
alter session set container=PAUL01;
set echo on
@online_files.sql

SQL> alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system.350.1078796917' online;
Database altered.

SQL> alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux.361.1078796917' online;
Database altered.

SQL> alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1.482.1078796933' online;
Database altered.

SQL> alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2.483.1078796939' online;
Database altered.

Enable/start redo apply of the physical standby database in the Data Guard Broker (5 Minutes)

. oraenv <<< SAMMY01B1
dgmgrl /
show configuration
edit database 'SAMMY01B' set state='apply-on';
exit

DGMGRL> show configuration

Configuration - SAMMY01

  Protection Mode: MaxAvailability
  Members:
  SAMMY01A - Primary database
    SAMMY01B - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 49 seconds ago)

DGMGRL> edit database 'SAMMY01B' set state='apply-on';
Succeeded.

Check the status of the PDB datafiles on the standby (20 Minutes)

. oraenv <<< SAMMY01B1
sqlplus / as sysdba
set lines 180
set pages 100
col name for a90
col error for a8

select name, status from v$datafile;

NAME										  STATUS
------------------------------------------------------------------------------------------ -------
+DATA/SAMMY01B/DATAFILE/system.450.1078092817					  SYSTEM
+DATA/SAMMY01B/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/system.451.1078092819              SYSTEM
+DATA/SAMMY01B/DATAFILE/sysaux.452.1078092833				                  ONLINE
+DATA/SAMMY01B/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/sysaux.453.1078092837	  ONLINE
+DATA/SAMMY01B/DATAFILE/undotbs1.454.1078092845 					  ONLINE
+DATA/SAMMY01B/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/undotbs1.455.1078092845	  ONLINE
+DATA/SAMMY01B/DATAFILE/undotbs2.456.1078092853 					  ONLINE
+DATA/SAMMY01B/DATAFILE/users.457.1078092855					   ONLINE
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system.350.1078796917	   SYSTEM
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux.361.1078796917               RECOVER
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1.482.1078796933	   RECOVER
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2.483.1078796939	   RECOVER

Note our PDB files are in RECOVER status, after some time they should change to ONLINE

select * from v$recover_file;
FILE# ONLINE  ONLINE_ ERROR       CHANGE# TIME	     CON_ID
---------- ------- ------- -------- ---------- --------- ----------
	13 ONLINE  ONLINE	       4648251 25-JUL-21	  3
	14 ONLINE  ONLINE	       4648253 25-JUL-21	  3
	15 ONLINE  ONLINE	       4648291 25-JUL-21	  3
	16 ONLINE  ONLINE	       4648312 25-JUL-21	  3
col name for a12
select name, recovery_status from v$pdbs where name = 'PAUL01';
NAME	     RECOVERY
------------ --------
PAUL01	     ENABLED

Wait 10 minutes and check file status again:

col name for a90
select name, status from v$datafile;

NAME										   STATUS
------------------------------------------------------------------------------------------ -------
+DATA/SAMMY01B/DATAFILE/system.450.1078092817					   SYSTEM
+DATA/SAMMY01B/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/system.451.1078092819	   SYSTEM
+DATA/SAMMY01B/DATAFILE/sysaux.452.1078092833					   ONLINE
+DATA/SAMMY01B/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/sysaux.453.1078092837	   ONLINE
+DATA/SAMMY01B/DATAFILE/undotbs1.454.1078092845 					   ONLINE
+DATA/SAMMY01B/C7427038C3E16E09E0536538A8C0EA0E/DATAFILE/undotbs1.455.1078092845	   ONLINE
+DATA/SAMMY01B/DATAFILE/undotbs2.456.1078092853 					   ONLINE
+DATA/SAMMY01B/DATAFILE/users.457.1078092855					   ONLINE
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system.350.1078796917	   SYSTEM
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux.361.1078796917	   ONLINE
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1.482.1078796933	   ONLINE
+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2.483.1078796939	   ONLINE

Validate the standby database in Data Guard Broker (5 Minutes)

. oraenv <<< SAMMY01B1
dgmgrl /
show configuration;
validate database 'SAMMY01B';
exit

DGMGRL> show configuration;

Configuration - SAMMY01

  Protection Mode: MaxAvailability
  Members:
  SAMMY01A - Primary database
    SAMMY01B - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 55 seconds ago)

DGMGRL> validate database 'SAMMY01B';

  Database Role:     Physical standby database
  Primary Database:  SAMMY01A

  Ready for Switchover:  Yes
  Ready for Failover:    Yes (Primary Running)

  Managed by Clusterware:
    SAMMY01A:  YES            
    SAMMY01B:  YES            

  Temporary Tablespace File Information:
    SAMMY01A TEMP Files:  3
    SAMMY01B TEMP Files:  2

  Log Files Cleared:
    SAMMY01A Standby Redo Log Files:  Cleared
    SAMMY01B Online Redo Log Files:   Not Cleared
    SAMMY01B Standby Redo Log Files:  Available

reinstate RMAN settings (5 Minutes)

. oraenv <<< SAMMY01A1
rman target /
show archivelog deletion policy;
configure archivelog deletion policy to <Previous Setting>;

review alertlog on standby (5 Minutes)

Completed: ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL
2021-07-25T01:53:38.029552+01:00
Switch of datafile 13 complete to datafile copy 
  checkpoint is 4648251
Switch of datafile 14 complete to datafile copy 
  checkpoint is 4648253
Switch of datafile 15 complete to datafile copy 
  checkpoint is 4648291
Switch of datafile 16 complete to datafile copy 
  checkpoint is 4648312
2021-07-25T01:59:28.079419+01:00
PAUL01(3):alter pluggable database enable recovery
PAUL01(3):Completed: alter pluggable database enable recovery
2021-07-25T02:00:24.914359+01:00
alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system.350.1078796917' online
ORA-1516 signalled during: alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system.350.1078796917' online...
alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux.361.1078796917' online
ORA-1516 signalled during: alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux.361.1078796917' online...
alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1.482.1078796933' online
ORA-1516 signalled during: alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1.482.1078796933' online...
alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2.483.1078796939' online
ORA-1516 signalled during: alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2.483.1078796939' online...
2021-07-25T02:00:49.558759+01:00
PAUL01(3):alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system.350.1078796917' online
PAUL01(3):Completed: alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/system.350.1078796917' online
PAUL01(3):alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux.361.1078796917' online
PAUL01(3):Completed: alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/sysaux.361.1078796917' online
PAUL01(3):alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1.482.1078796933' online
PAUL01(3):Completed: alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs1.482.1078796933' online
PAUL01(3):alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2.483.1078796939' online
PAUL01(3):Completed: alter database datafile '+DATA/SAMMY01B/C74107E1AD031A39E0536538A8C075C6/DATAFILE/undotbs2.483.1078796939' online
2021-07-25T02:02:13.269350+01:00
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT  NODELAY
2021-07-25T02:02:13.279317+01:00
Attempt to start background Managed Standby Recovery process (SAMMY01B1)
Starting background process MRP0
2021-07-25T02:02:13.316838+01:00
MRP0 started with pid=43, OS id=26095 
2021-07-25T02:02:13.319810+01:00
Background Managed Standby Recovery process started (SAMMY01B1)
2021-07-25T02:02:18.367343+01:00
Starting single instance redo apply (SIRA) 
 Started logmerger process
2021-07-25T02:02:18.480603+01:00
.... (PID:14744): Managed Standby Recovery starting Real Time Apply
2021-07-25T02:02:18.581043+01:00
max_pdb is 3
2021-07-25T02:02:18.854872+01:00
Parallel Media Recovery started with 4 slaves
2021-07-25T02:02:18.949170+01:00
stopping change tracking
2021-07-25T02:02:19.003289+01:00
TT02 (PID:26165): LOG_FILE_NAME_CONVERT is not defined, stop clearing ORLs
2021-07-25T02:02:19.130065+01:00
PR00 (PID:26148): Media Recovery Waiting for T-2.S-34 (in transit)
2021-07-25T02:02:19.138130+01:00
Recovery of Online Redo Log: Thread 2 Group 11 Seq 34 Reading mem 0
  Mem# 0: +DATA/SAMMY01B/ONLINELOG/group_11.462.1078092927
PR00 (PID:26148): Media Recovery Waiting for T-1.S-44 (in transit)
2021-07-25T02:02:19.218324+01:00
Recovery of Online Redo Log: Thread 1 Group 8 Seq 44 Reading mem 0
  Mem# 0: +DATA/SAMMY01B/ONLINELOG/group_8.459.1078092919
2021-07-25T02:02:19.333275+01:00
Completed: ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT  NODELAY
2021-07-25T02:02:19.787448+01:00
ALTER SYSTEM SET remote_listener=' rac-b-scan:1521' SCOPE=MEMORY SID='SAMMY01B1';
2021-07-25T02:02:19.790316+01:00
ALTER SYSTEM SET listener_networks='' SCOPE=MEMORY SID='SAMMY01B1';
2021-07-25T02:05:19.086304+01:00
Datafile 13 added to flashback set
Datafile 14 added to flashback set
Datafile 15 added to flashback set
Datafile 16 added to flashback set

perform a site switch to the standby and back to the Primary to ensure all is working as expected after implementing (30 Minutes)

Will not document as standard dataguard switchover commands.