In this post, I will demonstrate how we can recover a pluggable database’s XML manifest file in the event of the the XML manifest file being lost or corrupted. When we UNPLUG a pluggable database from a container (CDB), we use a XML manifest file to store the metadata (description) related to the UNPLUGGED pluggable database. We can use this XML manifest file to PLUG the UNPLUGGED pluggable database later to any compatible container database (CDB).
In the following example, I am going to demonstrate the method to recover a XML manifest file in the event of the XML manifest file being lost or corrupted. To start with my demonstration, I have a container database with a number of pluggable databases as shown below.
---// ---// list of pluggable databases //--- ---// SQL> show pdbs CON_ID CON_NAME OPEN MODE RESTRICTED ---------- ------------------------------ ---------- ---------- 2 PDB$SEED READ ONLY NO 3 CDB1_PDB_1 READ WRITE NO 4 CDB1_PDB_2 READ WRITE NO 5 CDB1_PDB_4 READ WRITE NO
Let’s UNPLUG one of these pluggable databases.
---// ---// UNPLUG a pluggable database //--- ---// SQL> alter pluggable database CDB1_PDB_4 close; Pluggable database altered. SQL> alter pluggable database CDB1_PDB_4 unplug into '/data/oracle/orpcdb1/template/cdb1_pdb4.xml'; Pluggable database altered.
We have UNPLUGGED the pluggable database with name CDB1_PDB_4 by keeping the PDB metadata (description) in the XML manifest file ‘/data/oracle/orpcdb1/template/cdb1_pdb4.xml’. We can later use this XML manifest file to PLUG the pluggable database back to any compatible container database (CDB).
Let’s drop the UNPLUGGED pluggable database from the current container. I am going to keep the datafiles, so that we can later PLUG the pluggable database back to the container.
---// ---// drop UNPLUGGED pluggable database from container //--- ---// SQL> drop pluggable database CDB1_PDB_4 keep datafiles; Pluggable database dropped. SQL> show pdbs CON_ID CON_NAME OPEN MODE RESTRICTED ---------- ------------------------------ ---------- ---------- 2 PDB$SEED READ ONLY NO 3 CDB1_PDB_1 READ WRITE NO 4 CDB1_PDB_2 READ WRITE NO
We have dropped the UNPLUGGED pluggable database CDB1_PDB_4 from the container. For the purpose of this demonstration, I have corrupted (artificially) the XML manifest file ‘/data/oracle/orpcdb1/template/cdb1_pdb4.xml’ which I had used to UNPLUG the pluggable database.
Now, I am going to try PLUGGING the UNPLUGGED pluggable database back to the container as shown below.
---// ---// PLUG the UNPLUGGED pluggable database back to container //--- ---// SQL> create pluggable database CDB1_PDB_4 using '/data/oracle/orpcdb1/template/cdb1_pdb4.xml' 2 NOCOPY 3 TEMPFILE REUSE; create pluggable database CDB1_PDB_4 using '/data/oracle/orpcdb1/template/cdb1_pdb4.xml' * ERROR at line 1: ORA-65026: XML metadata file error : LPX-00007: unexpected end-of-file encountered
Since, I had corrupted (artificially) the XML manifest file; I am seeing an ERROR (ORA-65026) while trying to PLUG the UNPLUGGED pluggable database using the XML manifest file. In this case, we will not be able to PLUG the UNPLUGGED database, until we have a VALID XML manifest file representing the metadata (description) of the UNPLUGGED pluggable database.
Here, DBMS_PDB package comes to our rescue. Oracle provides the DBMS_PDB.RECOVER procedure, which can be used to regenerate (recover) the XML manifest file for an UNPLUGGED pluggable database. This procedure has the following syntax.
---// ---// Syntax for DBMS_PDB.RECOVER procedure //--- ---// DBMS_PDB.RECOVER ( pdb_descr_file IN VARCHAR2, pdb_name IN VARCHAR2, filenames IN VARCHAR2);
Where:-
pdb_descr_file | Path (Name) of the XML manifest file to store pluggable database metadata (description) |
pdb_name | Name of the pluggable database |
filenames | Comma-separated list of paths/directories containing datafiles for the pluggable database |
The DBMS_PDB.RECOVER procedure takes three arguments as shown above. We can pass any path/name for the XML manifest file as well as any name for the pluggable database. However, we must know and pass the location of all the datafiles of the pluggable database for which we want to recover the manifest file.
Let’s recover the XML manifest file for the UNPLUGGED pluggable database CDB1_PDB_4. In my case all the datafiles for CDB1_PDB_4 are located under /data/oracle/orpcdb1/cdb1_pdb_4/ location. I will use this datafile location (filenames) to recover the XML file as shown below.
---// ---// recovering XML manifest file (using exact PDB name) //--- ---// SQL> BEGIN 2 DBMS_PDB.RECOVER ( 3 pdb_descr_file => '/data/oracle/orpcdb1/template/cdb1_pdb4_recover.xml', 4 pdb_name => 'CDB1_PDB_4', 5 filenames => '/data/oracle/orpcdb1/cdb1_pdb_4/' 6 ); 7 END; 8 / PL/SQL procedure successfully completed. SQL> !ls -lrt /data/oracle/orpcdb1/template/cdb1_pdb4_recover.xml -rw-r--r-- 1 oracle dba 2451 Apr 19 00:38 /data/oracle/orpcdb1/template/cdb1_pdb4_recover.xml ---// ---// recovering XML manifest file (using different PDB name) //--- ---// SQL> BEGIN 2 DBMS_PDB.RECOVER ( 3 pdb_descr_file => '/data/oracle/orpcdb1/template/cdb1_pdb4_recover1.xml', 4 pdb_name => 'CDB1_PDB_5', 5 filenames => '/data/oracle/orpcdb1/cdb1_pdb_4/' 6 ); 7 END; 8 / PL/SQL procedure successfully completed. SQL> !ls -lrt /data/oracle/orpcdb1/template/cdb1_pdb4_recover1.xml -rw-r--r-- 1 oracle dba 2451 Apr 19 00:42 /data/oracle/orpcdb1/template/cdb1_pdb4_recover1.xml
As I mentioned earlier, we need not pass the same pluggable database name to be able to recover the XML manifest file. In the above examples, I have recovered the XML manifest file using both EXACT and DIFFERENT pluggable database name. The only parameter that needs the exact (original) information is the filenames location of the UNPLUGGED pluggable database.
Once, the XML manifest file is recovered, we should be able to plug the pluggable database back to any compatible container using the recovered XML manifest file as shown below.
---// ---// PLUG the UNPLUGGED pluggable database using recovered XML manifest file //--- ---// SQL> create pluggable database CDB1_PDB_5 using '/data/oracle/orpcdb1/template/cdb1_pdb4_recover1.xml' 2 NOCOPY 3 TEMPFILE REUSE; Pluggable database created. SQL> show pdbs CON_ID CON_NAME OPEN MODE RESTRICTED ---------- ------------------------------ ---------- ---------- 2 PDB$SEED READ ONLY NO 3 CDB1_PDB_1 READ WRITE NO 4 CDB1_PDB_2 READ WRITE NO 5 CDB1_PDB_5 MOUNTED SQL> alter pluggable database CDB1_PDB_5 open; Pluggable database altered. SQL> alter session set container=CDB1_PDB_5; Session altered. SQL> select name from v$datafile; NAME -------------------------------------------------------------------------------- /data/oracle/orpcdb1/undotbs01.dbf /data/oracle/orpcdb1/cdb1_pdb_4/sysaux01.dbf /data/oracle/orpcdb1/cdb1_pdb_4/users01.dbf /data/oracle/orpcdb1/cdb1_pdb_4/system01.dbf
As expected, we are now able to PLUG the UNPLUGGED pluggable database back to the container (Thanks to DBMS_PDB.RECOVER procedure to come to our rescue).