Multitenant Architecture and Pluggable Databases
Multitenant Architecture and Pluggable Databases tests CDB/PDB structure and the administrative tasks that differ from a non-CDB.
Structure
A CDB contains CDB$ROOT, PDB$SEED as a read-only template, and one or more PDBs. Each PDB has its own data dictionary, users and service, but shares the instance and background processes. Common users carry the C## prefix and exist in root and in every PDB; local users exist in a single PDB. CDB_ views return container-wide rows, and the CONTAINERS() clause queries a PDB-level view from the root.
Operations
CREATE PLUGGABLE DATABASE pdb1 ADMIN USER p_admin IDENTIFIED BY password FILE_NAME_CONVERT=('/pdbseed/','/pdb1/'); then ALTER PLUGGABLE DATABASE pdb1 OPEN and SAVE STATE. Unplug writes an XML manifest with UNPLUG INTO, then DROP PLUGGABLE DATABASE ... KEEP DATAFILES; plug in elsewhere with CREATE PLUGGABLE DATABASE ... USING ('manifest.xml') COPY, MOVE or NOCOPY. Local undo (LOCAL_UNDO_ENABLED=TRUE, the 19c default) enables PDB point-in-time recovery and FLASHBACK PLUGGABLE DATABASE.
Worked example
A developer connected to the root as SYS runs CREATE USER app_user IDENTIFIED BY password and gets ORA-65096: invalid common user or role name. The root accepts only common users, which the C## prefix marks. The right answer is to connect to the target PDB and create a local user there; creating C##APP_USER in the root would give a user present in every container whose objects are not what the application expects.
Traps
Creating local users in CDB$ROOT; assuming a PDB has its own SGA or background processes; forgetting to open a PDB after creation; dropping a PDB without checking the manifest and backups; expecting every parameter to be changeable from inside a PDB; confusing common and local privilege scope.