The architecture of Oracle Database is undergoing its most significant transformation in the last 20 years. Starting with Oracle Database 21c, the creation of databases in the traditional Non-CDB (non-multitenant) configuration has been completely deprecated, making the multitenant (CDB/PDB) configuration the only option. Furthermore, this policy is continued and strengthened in Oracle 26ai, the next-generation Long Term Support (LTS) release, where integration with AI functions also proceeds on the premise of container technology.
The multitenant architecture itself was introduced in Oracle 12c and already has a history of over 10 years. The procedures explained in this article are standard operational practices that can be used not only for the latest 26ai but also for the currently mainstream 19c and earlier versions.
The simple formula of “Instance Startup = DB Available” no longer applies. With the introduction of container technology, the concepts of resource management, security, and backup change fundamentally.
In this article, we will explain “Startup/Shutdown, Connection, User Management, Backup, and Parameter Settings”—which are essential in a multitenant environment—in detail, including the background of “why we do it this way,” rather than just listing commands. Please use this as a compilation of operational know-how explained in this blog so far, and for your daily tasks or creating detailed procedure manuals.
[reference]
Oracle AI Database 26ai coming soon for Linux x86-64 on-premises platforms | database
- 0. [Diagram] Detailed Explanation of CDB/PDB Architecture
- 1. Startup, Shutdown, and Connection Practices (Detailed)
- 2. Common Users vs. Local Users & Privilege Management (Deep Dive)
- 3. Initialization Parameter Settings and Hierarchy
- 4. PDB Cloning Techniques
- 5. RMAN Backup and Recovery
- 6. Using Data Pump (expdp/impdp)
- 7. Key to Operational Monitoring: Utilizing CDB Views
- FAQ (Frequently Asked Questions – Extended)
- Summary: Hurry to Update Your Operation Manuals
0. [Diagram] Detailed Explanation of CDB/PDB Architecture
Before diving into operations, let’s understand the internal structure of how this “multitenant configuration” works a bit deeper. Understanding this will sharpen your intuition for troubleshooting.
Mechanism: Resources are “Shared”, Data is “Separated”
In the traditional (Non-CDB) model, a memory area on the OS (SGA) and background processes (PMON, SMON, DBWR, LGWR, etc.) were started for each database. In a CDB configuration, multiple databases (PDBs) virtually coexist within one huge vessel (CDB).
+-------------------------------------------------------------------------------------+
| CDB (Container Database) / Instance |
| +-------------------------------------------------------------------------------+ |
| | Memory (SGA) / Processes (BG) [Shared] | |
| | * REDO log buffer and Shared Pool are shared by everyone | |
| +-------------------------------------------------------------------------------+ |
| | | | | |
| +--------------+ +--------------+ +--------------+ +--------------+ |
| | CDB$ROOT | | PDB$SEED | | PDB1 (App) | | PDB2 (Dev) | |
| | (Mgmt Area) | | (Template) | | (Production) | | (Development)| |
| | Metadata | | Read Only | | HR App | | Verify Env | |
| +--------------+ +--------------+ +--------------+ +--------------+ |
| | | | | |
| +--------------+ +--------------+ +--------------+ +--------------+ |
| | System Defs | | Template Data| | Customer/Sale| | Test Data | |
| | (Datafiles) | | (Datafiles) | | (Datafiles) | | (Datafiles) | |
| | Control File | | | | | | | |
| | Redo Logs | | | | | | | |
| +--------------+ +--------------+ +--------------+ +--------------+ |
+-------------------------------------------------------------------------------------+
- CDB (Container Database):This is, so to speak, the “entire apartment building.” From the OS perspective, only one set of processes is running.The Control File and REDO log files are shared across the entire CDB. In other words, log switches and checkpoints affect all PDBs.
- CDB$ROOT:The “Landlord (Manager’s Office).”It holds only the dictionary information (metadata) to manage all containers.You must not create business data (tables, etc.) here. It is like living in the manager’s office.
- PDB (Pluggable Database):The “Individual Rooms.” From the application’s perspective, it looks like an independent database.Each PDB has its own SYSTEM and SYSAUX tablespaces.Local UNDO mode (Recommended): In recent versions, it is standard for each PDB to have its own UNDO tablespace, facilitating Flashback operations at the PDB level.
- PDB$SEED:The “Model Room (Template).” It is read-only.When creating a new PDB, it is created at high speed by internally copying this SEED.
Why this configuration? (Benefits of CDB)
This is not just a forced migration; adoption is progressing in many companies because there are clear operational benefits.
- Improved Density and Cost Reduction:Previously, 10 DBs required 10 sets of background processes. With CDB, only 1 set is needed, dramatically saving OS resources (especially memory and process count).
- Operational Agility (Portability):A PDB can be treated as a “collection of files and metadata.”By UNPLUGGING (detaching) and PLUGGING (attaching) into a CDB on another server, moving or cloning a database can be done with the ease of copying files. You can also upgrade simply by moving to a new CDB that has patches applied.
- Centralized Management and Role Division:
- Patching: If you patch the CDB (Landlord), it is reflected in all PDBs (Tenants) (Note: Individual PDB patching is also possible).
- Role Division: Clear separation of privileges is possible, such as “Infrastructure Admin monitors the whole CDB” and “App Developer operates freely only within the PDB.”
Conclusion: CDB/PDB Operation Command Cheatsheet
First, I have organized the commands frequently used in the field into an extended list. You should be able to type these from memory.
| Operation Category | Purpose | Command / Key Points |
| Startup/Shutdown | Start entire CDB | sqlplus / as sysdba → STARTUP |
| Check status of all PDBs | SHOW PDBS or SELECT name, open_mode FROM v$pdbs; | |
| Open specific PDB | ALTER PLUGGABLE DATABASE <pdb_name> OPEN; | |
| Open all PDBs at once | ALTER PLUGGABLE DATABASE ALL OPEN; | |
| Auto-start setting | ALTER PLUGGABLE DATABASE <pdb_name> SAVE STATE; | |
| Connection | Direct connection to PDB | sqlplus user/pass@<host>:<port>/<service_name> |
| Switch container | ALTER SESSION SET CONTAINER = <pdb_name>; | |
| Check current location | SHOW CON_NAME | |
| User | Create Local User | After connecting to PDB: CREATE USER <name> ... (No c## needed) |
| Create Common User | In CDB$ROOT: CREATE USER c##<name> ... | |
| Parameters | Change per PDB | ALTER SYSTEM SET <param>=<val> SCOPE=BOTH; (Run inside PDB) |
| Cloning | Create PDB Clone | CREATE PLUGGABLE DATABASE <new> FROM <source>; |
| Verification | View info for all PDBs | SELECT * FROM CDB_USERS ... (Use CDB_ instead of DBA_) |
1. Startup, Shutdown, and Connection Practices (Detailed)
In a multitenant environment, inquiries like “The instance is up, but I can’t connect” occur frequently. In most cases, this is due to missing PDB lifecycle management.
Instance (CDB) and PDB Lifecycle Management
Even if you STARTUP the CDB, the PDBs default to the MOUNT state. This is equivalent to “the file system is just mounted in the OS,” and SQL cannot be issued.
Detailed Procedure: Setting up PDB Auto-start
Manually opening PDBs every time is an operational risk. Use the SAVE STATE feature to configure the system to restore the previous state after a CDB restart
-- 1. Connect to CDB (Instance) and Startup
-- *Same as traditional method
$ sqlplus / as sysdba
SQL> STARTUP;
-- 2. Check PDB status (MOUNT = Stopped, READ WRITE = Available)
-- CON_ID: 2 is always PDB$SEED
SQL> SHOW PDBS;
CON_ID CON_NAME OPEN_MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 MOUNTED -- *Not usable yet (Stopped)
4 PDB2 MOUNTED -- *Not usable yet (Stopped)
-- 3. Open the PDB (Set to READ WRITE)
-- To open only a specific PDB
SQL> ALTER PLUGGABLE DATABASE pdb1 OPEN;
-- To open all PDBs at once
SQL> ALTER PLUGGABLE DATABASE ALL OPEN;
-- 4. [Important] Save the current open state (Restart measure)
-- By executing this, PDB1 will automatically OPEN at the next instance startup
SQL> ALTER PLUGGABLE DATABASE pdb1 SAVE STATE;
-- Check saved states (dba_pdb_saved_states view)
SQL> SELECT con_name, state FROM dba_pdb_saved_states;
The Correct Way to Connect: Service Name and Listener Settings
In the 19c/26ai era, consider connections relying on the ORACLE_SID environment variable as dedicated to “Administrative Tasks (CDB Maintenance).” Connections from applications or development tools must use Service Name connection via Oracle Net (Listener).
Checking Listener Status
The listener automatically registers not only the service for the entire CDB but also service names for each PDB.
$ lsnrctl status
...
Service Summary...
Service "ORCLCDB" ... Instance "ORCLCDB" ... (Entire CDB)
Service "pdb1.example.com" ... Instance "ORCLCDB" ... (Dedicated to PDB1)
Service "pdb2.example.com" ... Instance "ORCLCDB" ... (Dedicated to PDB2)
tnsnames.ora Description Example
In the tnsnames.ora on developer PCs or AP servers, define aliases for each PDB as follows:
# Connection setting for PDB1
PDB1_APP =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = orasrv01)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = pdb1.example.com) # *Write the PDB service name here
)
)
Utilizing Container Switching (ALTER SESSION)
When a DBA works on the server, you can move between containers without exiting sqlplus every time.
-- Move from CDB$ROOT to PDB1
SQL> ALTER SESSION SET CONTAINER = pdb1;
SQL> SHOW CON_NAME;
CON_NAME
------------------------------
PDB1
-- Return to CDB$ROOT when work is done (Common users only)
SQL> ALTER SESSION SET CONTAINER = cdb$root;
2. Common Users vs. Local Users & Privilege Management (Deep Dive)
“User Creation” is the point most prone to errors. In the 26ai era, you must understand the concept of “Namespace Separation.”
Reasons for User Types and Naming Conventions
Why do Common Users need c##? It is to prevent “Name Collision.”
If a common user named scott and a local user named scott in PDB1 could be created simultaneously, it would be confusing which one is used at login. Therefore, there is a mandatory rule to add c## for users effective across the entire CDB.
| Type | Creation Location | Naming Rule | Role / Usage |
| Common User | CDB$ROOT | c## or C## prefix mandatory | DBA, integrated monitoring tools, backup operations. Accessible to all PDBs (depending on privileges). |
| Local User | Each PDB | No restrictions (same as traditional) | Business apps, developer schemas. Valid only within that PDB. Does not exist in other PDBs. |
[Important] The CONTAINER Clause and Pitfalls in Granting Privileges
In privilege management within a CDB environment, a CONTAINER clause has been added to specify “in which scope the privilege can be exercised.” The default behavior (CURRENT) when omitting this is the root cause of trouble.
Case Study of Problems: Why ORA-01031 Occurs
Case: Created a common user for overall management (c##admin), but cannot operate the PDB.
- DBA Operation:Connect to CDB$ROOT and execute GRANT DBA TO c##admin;. (Inner voice: “Okay, now c##admin has the strongest privileges.”)
- Actual Behavior:Since the CONTAINER clause was omitted, Oracle interprets it as CONTAINER=CURRENT. This means “Exercise DBA privileges only within the management area called CDB$ROOT.”
- Trouble Occurs:Connect to PDB1 as c##admin and try to create a table.→ Error! ORA-01031: insufficient privileges. (Reason: Inside PDB1, c##admin is treated as just a general user).
Correct Solution: Explicitly Specify CONTAINER=ALL
To enable privileges for a Common User in “all current PDBs and PDBs created in the future,” you must append CONTAINER=ALL.
-- Enable SYSDBA privilege in all PDBs (True Administrator Privilege)
SQL> GRANT SYSDBA TO c##admin CONTAINER=ALL;
-- Same for session privileges
SQL> GRANT CREATE SESSION TO c##admin CONTAINER=ALL;
-- [Comparison] The following is the behavior when omitted (Valid only in current container)
-- If executed in CDB$ROOT, privileges are invalid in PDBs
SQL> GRANT SELECT ANY TABLE TO c##admin; -- (Implicitly CONTAINER=CURRENT)
3. Initialization Parameter Settings and Hierarchy
Parameter settings also introduce the concepts of “Inheritance” and “Override.”
Not all initialization parameters can be freely changed per PDB. There are those that forcibly inherit the CDB$ROOT setting (unchangeable) and those that can be set independently for the PDB.
Parameter Hierarchy
- Global Value (CDB$ROOT): Default setting. If not specified, all PDBs use this value.
- Local Value (PDB): Value individually set on the PDB side. Prioritized over the Global Value.
Checking ISPDB_MODIFIABLE
Before changing a parameter, check if it can be changed per PDB.
-- Check if modifiable per PDB (e.g., open_cursors, processes)
SELECT name, ispdb_modifiable
FROM v$parameter
WHERE name IN ('open_cursors', 'sga_target', 'processes');
-- Result Example
-- open_cursors TRUE (Changeable per PDB. Adjustable to app requirements)
-- sga_target TRUE (Upper limit settable per PDB. Important for resource separation)
-- processes FALSE (Settable only for entire CDB! Total processes shared by all PDBs)
- FALSE:
ALTER SYSTEMinside the PDB will result in an error or be ignored for that parameter. The value set inCDB$ROOTapplies to all PDBs.
Execution Patterns for Changing Settings
-- Pattern 1: Individual setting per PDB (Override)
-- Want to increase cursor count only for Application A (PDB1)
SQL> ALTER SESSION SET CONTAINER = pdb1;
SQL> ALTER SYSTEM SET open_cursors = 2000 SCOPE=BOTH;
-- ^ Reflected only in this PDB1
-- Pattern 2: Change default value for entire CDB
SQL> ALTER SESSION SET CONTAINER = cdb$root;
SQL> ALTER SYSTEM SET open_cursors = 500 SCOPE=BOTH CONTAINER=ALL;
-- ^ Default changes for all PDBs that do not have individual settings, including future PDBs
4. PDB Cloning Techniques
One of the highlights of multitenant features is the “Hot Clone” function, which can copy a running PDB as is. Requests like “I want to create a development environment immediately using the latest snapshot of production data” can be met with a single command.
Hot Clone Execution Procedure (CREATE PLUGGABLE DATABASE)
Prerequisites:
- CDB is operating in ARCHIVELOG mode.
- Local UNDO mode (Recommended).
Important: Path Conversion with FILE_NAME_CONVERT (Non-OMF Environment)
In environments using Oracle Managed Files (OMF) (where db_create_file_dest is set), file placement is automatically managed by Oracle, so path specification is unnecessary.
However, if you are managing files manually without OMF, the FILE_NAME_CONVERT clause is mandatory. Without this, the new PDB tries to use the same file paths as the source PDB (e.g., /u01/oradata/pdb1/system01.dbf), causing a “File already exists” error.
Mechanism of FILE_NAME_CONVERT
It rewrites part of the source file path in the format FILE_NAME_CONVERT = (‘String to replace’, ‘String after replacement’).
Scenario Example
- Source (pdb_prod) Datafiles:/u01/oradata/CDB1/pdb_prod/system01.dbf/u01/oradata/CDB1/pdb_prod/users01.dbf
- Target Location (pdb_dev):/u01/oradata/CDB1/pdb_dev/system01.dbf/u01/oradata/CDB1/pdb_dev/users01.dbf
Execution Command Example: Create Development PDB (pdb_dev) by copying Production PDB (pdb_prod)
-- 1. Connect to CDB$ROOT
$ sqlplus / as sysdba
-- 2. Execute Clone (Specify FILE_NAME_CONVERT)
SQL> CREATE PLUGGABLE DATABASE pdb_dev FROM pdb_prod
FILE_NAME_CONVERT = ('/pdb_prod/', '/pdb_dev/');
-- Explanation:
-- Oracle looks for the string '/pdb_prod/' and replaces it with '/pdb_dev/' to generate files.
-- Directory '/u01/oradata/CDB1/pdb_dev/' must be created on the OS beforehand.
-- 3. Open it (It is in MOUNT state immediately after creation)
SQL> ALTER PLUGGABLE DATABASE pdb_dev OPEN;
-- 4. Check Service Name (Service named pdb_dev starts automatically)
SQL> SELECT name, open_mode FROM v$pdbs;
With just this, a “Copy DB” including all user data, privileges, and objects is completed. Work that used to take hours with Data Pump export/import is completed in just a few minutes (depending on data volume and disk speed).
5. RMAN Backup and Recovery
Backup strategies in a CDB environment offer flexibility. The standard is “Whole Backup,” but “Split Backup” is also effective for large-scale environments.
Backup Acquisition Strategy
Basically, execute by connecting to target / (CDB$ROOT).
$ rman target /
Strategy A: Whole CDB Backup [Basic/Recommended]
Management is the easiest. Back up CDB$ROOT, PDB$SEED, and all PDBs together.
- Command:
BACKUP DATABASE PLUS ARCHIVELOG;
Strategy B: Per-PDB Backup
Effective when update frequencies differ strictly per PDB or when there are terabyte-class PDBs.
- Command:
BACKUP PLUGGABLE DATABASE pdb1, pdb2 PLUS ARCHIVELOG;
Recovery per PDB (PDB PITR)
The greatest advantage of multitenant is that “you can stop and recover only the PDB where the failure occurred.” Other PDBs (other systems) can continue service.
Scenario: Accidentally deleted datafiles of PDB1
-- 1. Close the failed PDB (Other PDBs can remain running)
RMAN> ALTER PLUGGABLE DATABASE pdb1 CLOSE;
-- 2. Restore & Recover
-- Automatically finds and applies necessary backup pieces and archive logs
RMAN> RESTORE PLUGGABLE DATABASE pdb1;
RMAN> RECOVER PLUGGABLE DATABASE pdb1;
-- 3. Open the PDB
RMAN> ALTER PLUGGABLE DATABASE pdb1 OPEN;
6. Using Data Pump (expdp/impdp)
Data Pump, used for logical backup and migration, also has specific practices for multitenant.
[Important] Do Not Execute in CDB$ROOT; Oracle Net Connection is Mandatory
This is the point where beginners get stuck the most.
- **No Data in CDB$ROOT:** User data resides in PDBs. Even if you
expdpinCDB$ROOT\, you only extract management information. - Local Users Cannot Log in to CDB: PDB users (like
app_user) exist only in the PDB. Therefore, authentication will not even pass via CDB connections such as OS authentication (/ as sysdba).
Conclusion: Data Pump must be executed by “Specifying the TNS Service Name and treating it like a remote DB.”
Preparation and Execution Steps
Step 1: Create Directory Object (Inside PDB!)
Directory settings are also independent per PDB.
SQL> ALTER SESSION SET CONTAINER = pdb1;
SQL> CREATE OR REPLACE DIRECTORY dp_dir AS '/u01/app/oracle/admin/pdb1/dpdump';
SQL> GRANT READ, WRITE ON DIRECTORY dp_dir TO app_dev;
Step 2: Execute Export (expdp)
Always specify the connection string (@Service_Name).
# Correct Example: Log in directly to PDB specifying Service Name
$ expdp app_dev/Password123@localhost:1521/pdb1 \
DIRECTORY=dp_dir \
DUMPFILE=pdb1_schema.dmp \
LOGFILE=exp_pdb1.log \
SCHEMAS=app_dev \
METRICS=Y
METRICS=Y: Option to output progress status and throughput to the log (Recommended as it is useful).
7. Key to Operational Monitoring: Utilizing CDB Views
Traditional DBA_ views only show “information of the currently connected container.” To monitor the entire CDB cross-sectionally, use CDB_ views.
- DBA_ Views (e.g., DBA_USERS):Displays information only within the connected container.If connected to PDB1, only PDB1 info is visible; if CDB$ROOT, only CDB$ROOT info.
- CDB_ Views (e.g., CDB_USERS):Displays information cross-sectionally for all containers (ROOT, SEED, all PDBs).Typically used by connecting to CDB$ROOT.Identify “which PDB the info belongs to” using the CON_ID column.
Usage Example: Listing Datafile Usage for All PDBs
By executing in CDB$ROOT, you can monitor the total capacity without logging into individual PDBs.
-- Execute in CDB$ROOT
SELECT
p.pdb_name,
f.file_name,
round(f.bytes / 1024 / 1024, 2) as size_mb
FROM cdb_data_files f
JOIN cdb_pdbs p ON f.con_id = p.con_id
ORDER BY p.pdb_name;
FAQ (Frequently Asked Questions – Extended)
Q1: Can’t I open all PDBs with just the startup command?
A1: You cannot do this with standard functions alone. In the past, there was a technique to write a startup trigger (AFTER STARTUP TRIGGER), but the official best practice now is to use ALTER PLUGGABLE DATABASE ALL SAVE STATE;. Once you execute this, they will auto-start from the next time.
Q2: I am using SID instead of SERVICE_NAME in the application connection settings; will it work?
A2: No, it will not. In a CDB environment, there is only one instance (SID) (the entire CDB), and each PDB is distinguished by its service name. If you connect specifying SID, you will connect to CDB$ROOT and get a “Table not found” error. You need to rewrite SID= to SERVICE_NAME= in the connection string.
Q3: Can I use a Common User (c##user) for applications?
A3: It is deprecated. Common users have complex privilege management, and accidents due to missing CONTAINER clauses are prone to happen. Also, when moving a PDB to another CDB, inconsistencies may occur if the same common user does not exist at the destination. Please use highly portable “Local Users” for applications.
Q4: I want to clone a development PDB to create a test environment; is that possible?
A4: It is very easy. Hot cloning is possible with a single command CREATE PLUGGABLE DATABASE pdb_test FROM pdb_dev; even if the PDB is in OPEN state (Note: Requirements such as Local UNDO mode and ARCHIVELOG mode are recommended).
Q5: Is access to the source PDB restricted during PDB clone creation?
A5: With the hot clone feature in 19c and later, it is possible to clone while the source PDB remains READ WRITE (updatable). There is no need to stop user operations.
Summary: Hurry to Update Your Operation Manuals
In the Oracle 21c/26ai era, always being conscious of “Which container am I connected to?” and “Scope of operation” is an essential skill for DBAs.
- Mandatory: Non-CDB is deprecated. There is no escape.
- Connection: Complete migration to Service Name connection (Oracle Net) is required.
- Privileges: Missing
CONTAINER=ALLfor common users is the biggest cause of trouble. - Monitoring: Utilize
CDB_views in addition toDBA_views.
This knowledge applies exactly the same way to Oracle Database on the cloud (OCI BaseDB, Exadata Database Service). Prepare for the coming mandatory multitenancy by updating your operation scripts and procedure manuals now.
This article explains based on Oracle Database 19c/21c (Basic concepts are common in 26ai, but screens and default values may differ).


コメント