Learn how to migrate an Oracle 19c Pluggable Database (PDB) using the Unplug/Plug method between different servers in a step-by-step and professional way. This guide explains the complete process of moving a PDB from one CDB to another across separate Linux hosts, including pre-checks, unplugging from the source database, copying datafiles, plugging into the target CDB, and post-migration validation. It also covers essential best practices, compatibility checks, and datapatch execution to ensure a smooth and error-free migration in Oracle Database 19c environments.
Environment Details:
| Component | Value |
|---|---|
| Source Host and OS Platform | orakldba, Oracle Linux 9.4 |
| Target Host and OS Platform | primary, Oracle Linux 9.4 |
| Source CDB Name | CDB1 (19.30) |
| Target CDB Name | CDB2 (19.30) |
| Source PDB Name | ORCLPDB |
| Method | Unplug → Plug |
Important Notes:
✔ Source and target CDB must be same version or target is higher version
✔ Check compatibility before plugSteps to Migrate a PDB Using Unplug/Plug on Different Server (Cross-Host Migration):
- Check Source PDB Status (CDB1)
- Verify Component & Version Compatibility (CDB1 and CDB2)
- Take Full RMAN Backup of Source CDB (Mandatory Best Practice)
- Close the PDB in Source CDB1
- Unplug the PDB from Source CDB1 and Generate XML Descriptor File
- Drop PDB from Source CDB1 (Keep Datafiles)
- Verify XML Metadata File at Source OS Level
- Copy XML File and PDB Datafiles from Source Server to Target Server
- Check Target CDB Status (CDB2)
- Verify Plug Compatibility on Target CDB2 Using XML File
- Set Proper Oracle Environment on Target Server (ORACLE_HOME, ORACLE_SID)
- Plug PDB into Target CDB2 Using CREATE PLUGGABLE DATABASE (COPY Method)
- Verify PDB Registration in Target CDB2
- Open the Plugged PDB in Target CDB2
- Save PDB State for Auto Startup After Restart
- Verify Database Components After Migration
- Check Invalid Objects in PDB
- Recompile Invalid Objects Using utlrp.sql
- Recheck Invalid Objects After Compilation
Check Source PDB Status (CDB1):
[oracle@orakldba ~]$ ps -ef | grep pmon
oracle 5387 1 0 04:24 ? 00:00:00 ora_pmon_CDB1
oracle 6508 4455 0 04:26 pts/0 00:00:00 grep --color=auto pmon
[oracle@orakldba ~]$
[oracle@orakldba ~]$
[oracle@orakldba ~]$ export ORACLE_SID=CDB1
[oracle@orakldba ~]$
[oracle@orakldba ~]$
[oracle@orakldba ~]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Sun May 24 04:27:25 2026
Version 19.31.0.0.0
Copyright (c) 1982, 2026, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.31.0.0.0
SQL>
SQL> select name,database_role,open_mode,cdb from v$database;
NAME DATABASE_ROLE OPEN_MODE CDB
--------- ---------------- -------------------- ---
CDB1 PRIMARY READ WRITE YES
SQL>
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB READ WRITE NO
SQL>Verify Component & Version Compatibility (CDB1 and CDB2):
Details from CDB1:
=============================
SQL> select name,database_role,open_mode,cdb from v$database;
NAME DATABASE_ROLE OPEN_MODE CDB
--------- ---------------- -------------------- ---
CDB1 PRIMARY READ WRITE YES
SQL>
SQL> select comp_name, version, status from dba_registry;
COMP_NAME VERSION STATUS
-------------------------------------------------- --------------- --------------------------------------------
Oracle Database Catalog Views 19.0.0.0.0 VALID
Oracle Database Packages and Types 19.0.0.0.0 VALID
Oracle Real Application Clusters 19.0.0.0.0 OPTION OFF
JServer JAVA Virtual Machine 19.0.0.0.0 VALID
Oracle XDK 19.0.0.0.0 VALID
Oracle Database Java Packages 19.0.0.0.0 VALID
OLAP Analytic Workspace 19.0.0.0.0 VALID
Oracle XML Database 19.0.0.0.0 VALID
Oracle Workspace Manager 19.0.0.0.0 VALID
Oracle Text 19.0.0.0.0 VALID
Oracle Multimedia 19.0.0.0.0 VALID
Spatial 19.0.0.0.0 VALID
Oracle OLAP API 19.0.0.0.0 VALID
Oracle Label Security 19.0.0.0.0 VALID
Oracle Database Vault 19.0.0.0.0 VALID
15 rows selected.
SQL>
Details from CDB2:
=============================
SQL> select name,database_role,open_mode,cdb from v$database;
NAME DATABASE_ROLE OPEN_MODE CDB
--------- ---------------- -------------------- ---
CDB2 PRIMARY READ WRITE YES
SQL>
SQL> select comp_name, version, status from dba_registry;
COMP_NAME VERSION STATUS
-------------------------------------------------- --------------- --------------------------------------------
Oracle Database Catalog Views 19.0.0.0.0 VALID
Oracle Database Packages and Types 19.0.0.0.0 VALID
Oracle Real Application Clusters 19.0.0.0.0 OPTION OFF
JServer JAVA Virtual Machine 19.0.0.0.0 VALID
Oracle XDK 19.0.0.0.0 VALID
Oracle Database Java Packages 19.0.0.0.0 VALID
OLAP Analytic Workspace 19.0.0.0.0 VALID
Oracle XML Database 19.0.0.0.0 VALID
Oracle Workspace Manager 19.0.0.0.0 VALID
Oracle Text 19.0.0.0.0 VALID
Oracle Multimedia 19.0.0.0.0 VALID
Spatial 19.0.0.0.0 VALID
Oracle OLAP API 19.0.0.0.0 VALID
Oracle Label Security 19.0.0.0.0 VALID
Oracle Database Vault 19.0.0.0.0 VALID
15 rows selected.
SQL>Take Full RMAN Backup of Source CDB (Mandatory Best Practice):
run
{
allocate channel c1 device type disk;
backup database format '/u02/backup/full_db_%d_%T_%U.bkp';
backup archivelog all format '/u02/backup/arch_%d_%T_%U.bkp';
backup current controlfile format '/u02/backup/ctrl_%d_%T_%U.bkp';
backup spfile format '/u02/backup/spfile_%d_%T_%U.bkp';
release channel c1;
}Close the PDB in Source CDB1:
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB READ WRITE NO
SQL>
SQL> alter pluggable database ORCLPDB close immediate;
Pluggable database altered.
SQL>
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB MOUNTED
SQL>Unplug the PDB from Source CDB1 and Generate XML Descriptor File:
SQL>
SQL> alter pluggable database ORCLPDB unplug into '/u02/backup/ORCLPDB.xml';
Pluggable database altered.
SQL>Drop PDB from Source CDB1 (Keep Datafiles):
Removes registration but keeps physical files.
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB MOUNTED
SQL>
SQL> drop pluggable database ORCLPDB keep datafiles;
Pluggable database dropped.
SQL>
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
SQL>Verify XML File at OS Level (Source Server):
Confirm XML file exists and is valid size.
[oracle@orakldba ~]$
[oracle@orakldba ~]$ ls -ltrh /u02/backup/ORCLPDB.xml
-rw-r--r--. 1 oracle oinstall 7.5K May 24 15:42 /u02/backup/ORCLPDB.xml
[oracle@orakldba ~]$Copy Files to Target Server (CDB2):
Copy XML descriptor file, Copy all PDB datafiles (.dbf, tempfiles if required)
Create same datafiles directory as source database on target database server before copy all files.
[oracle@primary ~]$
[oracle@primary ~]$ mkdir -p /u01/app/oracle/oradata/CDB1/ORCLPDB
[oracle@primary ~]$
[oracle@orakldba ~]$
[oracle@orakldba ~]$ scp /u02/backup/ORCLPDB.xml oracle@192.168.1.8:/u02/backup/
oracle@192.168.1.8's password:
ORCLPDB.xml 100% 7672 1.2MB/s 00:00
[oracle@orakldba ~]$
[oracle@orakldba ~]$
[oracle@orakldba ~]$
[oracle@orakldba ~]$ scp /u01/app/oracle/oradata/CDB1/ORCLPDB/* oracle@192.168.###.##:/u01/app/oracle/oradata/CDB1/ORCLPDB/
oracle@192.168.###.##'s password:
sysaux01.dbf 100% 450MB 40.9MB/s 00:11
system01.dbf 100% 520MB 20.7MB/s 00:25
undotbs01.dbf 100% 270MB 17.4MB/s 00:15
users01.dbf 100% 5128KB 17.7MB/s 00:00
[oracle@orakldba ~]$Check Target CDB Status (CDB2):
Ensure CDB2 is up and running.
[oracle@primary ~]$ . oraenv
ORACLE_SID = [CDB2] ? CDB2
The Oracle base remains unchanged with value /u01/app/oracle
[oracle@primary ~]$
[oracle@primary ~]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Sun May 24 16:52:33 2026
Version 19.31.0.0.0
Copyright (c) 1982, 2026, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.31.0.0.0
SQL> select name, database_role, open_mode, cdb from v$database;
NAME DATABASE_ROLE OPEN_MODE CDB
--------- ---------------- -------------------- ---
CDB2 PRIMARY READ WRITE YES
SQL>
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
SQL>Check Plug Compatibility on Target CDB2:
Validate before plug-in operation.
SQL>
SQL> set serveroutput on;
SQL> declare
2 compatible boolean;
3 begin
4 compatible := DBMS_PDB.CHECK_PLUG_COMPATIBILITY(
5 pdb_descr_file => '/u02/backup/ORCLPDB.xml'
6 );
7 if compatible then
8 DBMS_OUTPUT.PUT_LINE('PDB is COMPATIBLE');
9 else
10 DBMS_OUTPUT.PUT_LINE('PDB is NOT COMPATIBLE');
11 end if;
12 end;
13 /
PDB is COMPATIBLE
PL/SQL procedure successfully completed.
SQL>Plug PDB into Target CDB2 (Cross Server):
Using COPY method (Recommended for different server/storage).
SQL> create pluggable database ORCLPDB
2 using '/u02/backup/ORCLPDB.xml'
3 copy
4 file_name_convert =
5 ('/u01/app/oracle/oradata/CDB1/ORCLPDB/','/u01/app/oracle/oradata/CDB2/ORCLPDB/');
Pluggable database created.
SQL>Verify PDB in Target CDB2:
Confirm PDB is registered.
SQL> select name, database_role, open_mode, cdb, pdb_name, status from v$database,dba_pdbs;
NAME DATABASE_ROLE OPEN_MODE CDB PDB_NAME STATUS
--------- ---------------- -------------------- --- --------------- ----------
CDB2 PRIMARY READ WRITE YES ORCLPDB NEW
CDB2 PRIMARY READ WRITE YES PDB$SEED NORMAL
SQL>
SQL>
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB MOUNTED
SQL>Open the Plugged PDB:
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB MOUNTED
SQL>
SQL>
SQL> alter pluggable database ORCLPDB open;
Pluggable database altered.
SQL>
SQL>
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB READ WRITE NO
SQL>Save PDB State (Auto Open After Restart):
SQL>
SQL> alter pluggable database ORCLPDB save state;
Pluggable database altered.
SQL>Verify Database Components After Migration:
SQL> alter session set container=ORCLPDB;
Session altered.
SQL>
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
3 ORCLPDB READ WRITE NO
SQL>
SQL> select comp_name, version, status from dba_registry;
COMP_NAME VERSION STATUS
-------------------------------------------------- ------------------------------ --------------------------------------------
Oracle Database Catalog Views 19.0.0.0.0 VALID
Oracle Database Packages and Types 19.0.0.0.0 VALID
Oracle Real Application Clusters 19.0.0.0.0 OPTION OFF
JServer JAVA Virtual Machine 19.0.0.0.0 VALID
Oracle XDK 19.0.0.0.0 VALID
Oracle Database Java Packages 19.0.0.0.0 VALID
OLAP Analytic Workspace 19.0.0.0.0 VALID
Oracle XML Database 19.0.0.0.0 VALID
Oracle Workspace Manager 19.0.0.0.0 VALID
Oracle Text 19.0.0.0.0 VALID
Oracle Multimedia 19.0.0.0.0 VALID
Spatial 19.0.0.0.0 VALID
Oracle OLAP API 19.0.0.0.0 VALID
Oracle Label Security 19.0.0.0.0 VALID
Oracle Database Vault 19.0.0.0.0 VALID
15 rows selected.
SQL>Check Invalid Objects in PDB:
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
3 ORCLPDB READ WRITE NO
SQL>
SQL> select count(*) from dba_objects where status='INVALID';
COUNT(*)
----------
0
SQL>Recompile Invalid Objects (Best Practice):
In our case, there are no invalid objects observed after migration completion. However, if any invalid objects are found after the migration, then execute utlrp.sql to recompile and resolve them.
SQL> @?/rdbms/admin/utlrp.sqlRecheck Invalid Objects After Compilation:
select count(*) from dba_objects where status='INVALID';I hope my written content will helped you. Your suggestions/feedback are most welcome from orakldba.com. Keep learning… Have a great day!!!
Please comment here for your any query related to above content. You can write to mail me through my Email.
Email :- orakldba@gmail.com
LinkedIn :- https://linkedin.com/in/prasantakirtaniya
Twitter :- https://twitter.com/prasantadba
Facebook Page :- https://www.facebook.com/orakldba
Website :- https://orakldba.com
ACE Profile :- https://ace.oracle.com/apex/ace/profile/prasantakirtaniya
