Home / Databases / Oracle

DatabasesHow-toAdvanced

Transformation: converting Oracle non-CDB databases to PDBs before the multitenant-only releases

Oracle 19c is the last release that supports the non-CDB architecture, so every database moving to 23ai must become a pluggable database. Check compatibility, describe the non-CDB, plug it into a CDB with NOCOPY or COPY, run noncdb_to_pdb.sql, and fix services and backups afterwards.

Deepak Bhardwaj3 min read

Applies toOracle Database 19c non-CDB sources into 19c CDBs (then upgrade), or directly with AutoUpgrade into 21c/23ai CDBs

Two routes

Route When
Manual: DBMS_PDB.DESCRIBE + plug in + noncdb_to_pdb.sql Same version (19c → 19c CDB); you want control
AutoUpgrade with target_cdb Upgrade and conversion in one run (e.g. 19c non-CDB → 23ai PDB). See the AutoUpgrade post

This post covers the manual route.

1. Pre-checks

  • Same database version and patch level (RU) in source and CDB, or plan an upgrade.
  • Character set compatible with the CDB (an AL32UTF8 CDB accepts most; a non-matching single-byte CDB doesn't).
  • Options and components installed in the non-CDB exist in the CDB (SELECT comp_name FROM dba_registry).
  • Space: NOCOPY reuses files in place (fast, no rollback without a backup); COPY duplicates them.

2. Describe the non-CDB

-- in the non-CDB, opened READ ONLY
SHUTDOWN IMMEDIATE;
STARTUP OPEN READ ONLY;
BEGIN
  DBMS_PDB.DESCRIBE(pdb_descr_file => '/u01/stage/salesdb.xml');
END;
/
SHUTDOWN IMMEDIATE;

3. Check compatibility from the CDB

-- in CDB$ROOT
SET SERVEROUTPUT ON
DECLARE
  ok BOOLEAN;
BEGIN
  ok := DBMS_PDB.CHECK_PLUG_COMPATIBILITY(pdb_descr_file => '/u01/stage/salesdb.xml', pdb_name => 'SALESPDB');
  DBMS_OUTPUT.PUT_LINE(CASE WHEN ok THEN 'COMPATIBLE' ELSE 'NOT COMPATIBLE' END);
END;
/
SELECT type, message, action FROM pdb_plug_in_violations WHERE name = 'SALESPDB' AND status <> 'RESOLVED';

Fix ERROR rows before continuing. WARNING rows (e.g. parameter differences) are usually acceptable, but read them.

4. Plug in

Take a backup of the non-CDB first, especially with NOCOPY.

CREATE PLUGGABLE DATABASE salespdb USING '/u01/stage/salesdb.xml' NOCOPY TEMPFILE REUSE;
-- or COPY with file name conversion:
-- CREATE PLUGGABLE DATABASE salespdb USING '/u01/stage/salesdb.xml' COPY
--   FILE_NAME_CONVERT = ('/u02/oradata/SALES/', '/u02/oradata/CDB1/salespdb/');

5. Convert the dictionary

ALTER SESSION SET CONTAINER = salespdb;
@?/rdbms/admin/noncdb_to_pdb.sql

This can take a while (it recompiles and rewrites dictionary objects). Then:

ALTER PLUGGABLE DATABASE salespdb OPEN;
ALTER PLUGGABLE DATABASE salespdb SAVE STATE;
SELECT name, open_mode, restricted FROM v$pdbs;

RESTRICTED = YES means there are unresolved violations; check pdb_plug_in_violations again.

6. After conversion

Area Action
Services Applications connect to the PDB service name (old SID-based connections break)
Users Local users moved with the PDB; common users (C##) exist only at CDB level
Backups RMAN now backs up the CDB; adjust scripts to BACKUP PLUGGABLE DATABASE or the whole CDB
Data Guard Standby must be a CDB too; plan the standby re-creation
Monitoring Point checks at the PDB service; container-aware queries (CON_ID)
Scheduler jobs, DB links Test; DB links referencing the old global name may need changes

Warning

With NOCOPY, the original non-CDB can no longer be opened as before, because its files now belong to the PDB. Your rollback is the backup from Step 4.

Checklist

  • Version, RU, character set and components match
  • Compatibility check clean
  • Backup taken before NOCOPY plug-in
  • noncdb_to_pdb.sql run, PDB unrestricted, state saved
  • Services, backups, Data Guard and monitoring updated