I have created a CDB using Oracles database configuration assistant (dbca).
While installing, I choosed to create a Pluggable database, too, called pdbvegdb01.
If you want to make a clone of a PDB, it's a relative simple process.
1. Check your current setup by connecting to the root container (CDB$ROOT), and issue the following query:
select C.PDB_ID,C.PDB_NAME,C.STATUS,C.CON_ID "container id", P.OPEN_MODE,P.restricted from CDB_PDBS C inner join V$PDBS P on C.CON_ID = P.CON_ID order by c.con_id;
PDB_ID | PDB_NAME | STATUS | container id | OPEN_MODE | RESTRICTED |
---|---|---|---|---|---|
2 | PDB$SEED | NORMAL | 2 | READ ONLY | NO |
3 | PDBVEGDB01 | NORMAL | 3 | READ WRITE | NO |
I would like to clone the PDBVEGDB01, to a new one, that I will name vpdb01.
2. Check if the root container uses OMF (Oracle Managed Files)
select name,value,DESCRIPTION from V$SYSTEM_PARAMETER WHERE NAME in( 'db_create_file_dest');
NAME | VALUE | DESCRIPTION |
---|---|---|
db_create_file_dest | /u02/oradata | default database location |
It does, and that means your new PDB will inherit this setting.
In this example, I would NOT like Oracle to manage the files in my PDB.
I want to place them in a folder called /u02/oradata/VPDB01.
3. Make directory on server:
mkdir -p /u02/oradata/VPDB01
4. Check the names and paths of the files being used by the source PDB:
select FILE_NAME from CDB_DATA_FILES where CON_ID=3 union select file_name from cdb_temp_files where con_id=3;The result of this union is:
FILE_NAME |
---|
/u02/oradata/CONTAINER#DB01/436546A3F70642C3E0537800A8C03C16/datafile/o1_mf_system_d4tytlns_.dbf |
/u02/oradata/CONTAINER#DB01/436546A3F70642C3E0537800A8C03C16/datafile/o1_mf_sysaux_d4tytlo2_.dbf |
/u02/oradata/CONTAINER#DB01/436546A3F70642C3E0537800A8C03C16/datafile/o1_mf_temp_d4tytlo2_.dbf |
/u02/oradata/CONTAINER#DB01/436546A3F70642C3E0537800A8C03C16/datafile/o1_mf_users_d4tyw5y9_.dbf |
All the above files must be accounted for in your clone script, when deciding not to continue using OMF.
5. If not already done, switch to the root container:
alter session set container = CDB$ROOT;
6. Close the source pdb, and open it read only:
alter PLUGGABLE database pdbvegdb01 CLOSE; alter PLUGGABLE database pdbvegdb01 OPEN READ ONLY;
7. Clone the source pdb. Notice that I have matched the source pdb's datafiles, one by one, with a file name of my choosing:
create PLUGGABLE DATABASE VPDB01 from pdbvegdb01 FILE_NAME_CONVERT=( '/u02/oradata/CONTAINER#DB01/436546A3F70642C3E0537800A8C03C16/datafile/o1_mf_system_d4tytlns_.dbf', '/u02/oradata/VPDB01/system01.dbf', '/u02/oradata/CONTAINER#DB01/436546A3F70642C3E0537800A8C03C16/datafile/o1_mf_sysaux_d4tytlo2_.dbf', '/u02/oradata/VPDB01/sysaux01.dbf', '/u02/oradata/CONTAINER#DB01/436546A3F70642C3E0537800A8C03C16/datafile/o1_mf_temp_d4tytlo2_.dbf', '/u02/oradata/VPDB01/temp01.dbf' '/u02/oradata/CONTAINER#DB01/436546A3F70642C3E0537800A8C03C16/datafile/o1_mf_users_d4tyw5y9_.dbf, '/u02/oradata/VPDB01/users01.dbf' );
Your sqlplus session should return "pluggable DATABASE created."
8. Open the source pdb for read/write:
alter pluggable database pdbvegdb01 close; alter pluggable database pdbvegdb01 open read write;
You now see that your freshly cloned database is in status NEW and is MOUNTED, but not open:
PDB_ID | PDB_NAME | STATUS | container id | OPEN_MODE | RESTRICTED |
---|---|---|---|---|---|
2 | PDB$SEED | NORMAL | 2 | READ ONLY | NO |
3 | PDBVEGDB01 | NORMAL | 3 | READ WRITE | NO |
6 | VPDB01 | NEW | 6 | MOUNTED |
9. Open the pdb by switching your session container to the newly cloned pdb
alter session set container=vpdb01;Just to verify, check the open mode of the container.
select CON_ID,DBID,name,OPEN_MODE from v$containers order by con_id;You should have one row worth of output, since you switched from the root container to the pdb container:
CON_ID | DBID | NAME | OPEN_MODE |
---|---|---|---|
6 | 2049231443 | VPDB01 | MOUNTED |
10. Open the pluggable database:
alter pluggable database vpdb01 open;
For the last step to work, you strictly don't need to switch container, it can be done while you have your session set to the root container as well.
But it demonstrates the ability for the DBA to switch containers and work isolated with them, as though they were separate databases.
Finally, let's switch back to the root container and check the status of our PDB's:
alter session set container = CDB$ROOT; select C.PDB_ID,C.PDB_NAME,C.STATUS,C.CON_ID "container id", P.OPEN_MODE,P.restricted from CDB_PDBS C inner join V$PDBS P on C.CON_ID = P.CON_ID order by c.con_id;Result:
PDB_ID | PDB_NAME | STATUS | container id | OPEN_MODE | RESTRICTED |
---|---|---|---|---|---|
2 | PDB$SEED | NORMAL | 2 | READ ONLY | NO |
3 | PDBVEGDB01 | NORMAL | 3 | READ WRITE | NO |
4 | VPDB01 | NORMAL | 4 | READ WRITE | NO |