Oracle 多租户架构(CDB / PDB)

Oracle 多租户架构(CDB / PDB)

适用版本:Oracle Database 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

多租户(Multitenant) 是 Oracle 12c 引入的架构[1],将数据库分为:

  • CDB(Container Database,容器数据库):根容器
  • PDB(Pluggable Database,可插拔数据库):业务数据库

19c:多租户成为标配(最多 3 个 PDB 免费授权)

23ai:所有数据库均为 CDB(强制多租户)


2. CDB 架构

2.1 容器结构

+---------------------------------------------+
| CDB$ROOT (Root Container)                   |
|   - SYSTEM / SYSAUX / UNDO / REDO           |
|   - Common Users / Common Roles             |
|   - Data Dictionary (元数据)                |
|   - 已安装的 Oracle Home                    |
+---------------------------------------------+
       │                │                │
       ▼                ▼                ▼
+-----------+    +-----------+    +-----------+
| PDB$SEED  |    | HRPDB     |    | SALESPDB  |
| (Seed)    |    | (HR 业务) |    | (销售业务)|
+-----------+    +-----------+    +-----------+

2.2 容器类型

容器作用默认存在
CDB$ROOT根容器,管理 PDB
PDB$SEED种子 PDB,创建 PDB 的模板
Application RootApplication Container 根可选
Application PDBApplication Container 中的 PDB可选
User PDB业务 PDB用户创建
Proxy PDB代理 PDB,指向外部 PDB可选

2.3 PDB 优势

  • 资源隔离:每个 PDB 独立资源
  • 管理集中:一个 CDB 管理多个 PDB
  • 快速迁移:插拔操作
  • 快速克隆:PDB 克隆
  • 运维简化:一次升级,多 PDB 受益

3. CDB 体系结构

3.1 内存与进程

+-------------------+
| CDB Instance      |
|   SGA + PGA       |
|   Background Proc |
+-------------------+


+-------------------+
| CDB$ROOT          |  ← 1 套后台进程
|   Data Dict Base  |  ← 共享后台进程
+-------------------+


+--------+--------+
|        |        |
PDB1    PDB2    PDB3

特点

  • 1 套后台进程:所有 PDB 共享
  • 1 个 SGA:所有 PDB 共享 SGA
  • 1 个 UNDO(19c 支持每个 PDB 独立 UNDO)
  • 1 个 Redo Log(19c 支持每个 PDB 独立 Redo)

3.2 数据字典隔离

CDB$ROOT:
  - OBJ$ 等基表:所有对象
  - DBA_OBJECTS:仅 ROOT 对象

PDB:
  - 共享 OBJ$ 基表(通过指针指向 ROOT)
  - DBA_OBJECTS:仅本 PDB 对象

机制:Container_id 区分

SELECT con_id, name, open_mode FROM v$pdbs;

--  CON_ID NAME      OPEN_MODE
--  2     PDB$SEED  READ ONLY
--  3     HRPDB     READ WRITE
--  4     SALESPDB  READ WRITE

4. 创建 CDB

4.1 DBCA 创建

dbca -silent -createDatabase \
  -templateName General_Purpose.dbc \
  -gdbName ORCL \
  -sid ORCL \
  -createAsContainerDatabase true \
  -numberOfPDBs 1 \
  -pdbName hrpdb \
  -pdbAdminPassword hr_pwd \
  -sysPassword sys_pwd \
  -systemPassword sys_pwd \
  -storageType FS \
  -datafileDestination /u01/oradata \
  -characterSet AL32UTF8 \
  -totalMemory 2048

4.2 手动创建

-- 1. 设置参数
ALTER SYSTEM SET enable_pluggable_database=TRUE SCOPE=SPFILE;

-- 2. 启动到 nomount
STARTUP NOMOUNT;

-- 3. 创建 CDB
CREATE DATABASE ORCL
  USER SYS IDENTIFIED BY ******
  USER SYSTEM IDENTIFIED BY ******
  LOGFILE GROUP 1 ('/u01/oradata/orcl/redo01.log') SIZE 100M,
          GROUP 2 ('/u01/oradata/orcl/redo02.log') SIZE 100M,
          GROUP 3 ('/u01/oradata/orcl/redo03.log') SIZE 100M
  EXTENT MANAGEMENT LOCAL
  DATAFILE '/u01/oradata/orcl/system01.dbf' SIZE 1G AUTOEXTEND ON
  SYSAUX DATAFILE '/u01/oradata/orcl/sysaux01.dbf' SIZE 1G AUTOEXTEND ON
  DEFAULT TABLESPACE users
  DEFAULT TEMPORARY TABLESPACE temp
  UNDO TABLESPACE undotbs1
  ENABLE PLUGGABLE DATABASE
    SEED FILE_NAME_CONVERT = 
      ('/u01/oradata/orcl/', '/u01/oradata/orcl/pdbseed/');

5. PDB 操作

5.1 创建 PDB

-- 从 PDB$SEED 创建
CREATE PLUGGABLE DATABASE hrpdb 
  ADMIN USER pdbadmin IDENTIFIED BY ****** 
  DEFAULT TABLESPACE users 
  DATAFILE '/u01/oradata/orcl/hrpdb/users01.dbf' SIZE 500M;

-- 从现有 PDB 克隆
CREATE PLUGGABLE DATABASE hrpdb_clone FROM hrpdb;

-- 插入 PDB
CREATE PLUGGABLE DATABASE hrpdb USING '/tmp/hrpdb.xml' 
  SOURCE_FILE_NAME_CONVERT=('/u01/oradata/orcl/hrpdb/','/u01/oradata/orcl/hrpdb/');

5.2 打开/关闭 PDB

-- 打开单个 PDB
ALTER PLUGGABLE DATABASE hrpdb OPEN;
ALTER PLUGGABLE DATABASE hrpdb CLOSE;

-- 打开所有 PDB
ALTER PLUGGABLE DATABASE ALL OPEN;
ALTER PLUGGABLE DATABASE ALL CLOSE;

-- 启动到指定状态
ALTER PLUGGABLE DATABASE hrpdb OPEN READ ONLY;
ALTER PLUGGABLE DATABASE hrpdb OPEN UPGRADE;

5.3 切换容器

-- 切换到 PDB
ALTER SESSION SET CONTAINER = hrpdb;

-- 切换到 CDB ROOT
ALTER SESSION SET CONTAINER = CDB$ROOT;

-- 查看当前容器
SELECT sys_context('USERENV','CON_NAME') FROM dual;

5.4 保存 PDB 状态

-- 保存打开状态(下次启动自动打开)
ALTER PLUGGABLE DATABASE hrpdb SAVE STATE;

-- 取消保存
ALTER PLUGGABLE DATABASE hrpdb DISCARD STATE;

详细内容见:Oracle PDB 操作与管理


6. Common User 与 Local User

6.1 Common User

-- 必须以 c## 或 C## 开头
CREATE USER c##admin IDENTIFIED BY ****** 
  DEFAULT TABLESPACE users 
  CONTAINER=ALL;

-- 在所有 PDB 中存在
GRANT CREATE SESSION TO c##admin CONTAINER=ALL;

6.2 Local User

-- 在 PDB 中创建
ALTER SESSION SET CONTAINER = hrpdb;
CREATE USER hr_admin IDENTIFIED BY ****** DEFAULT TABLESPACE users;
GRANT CREATE SESSION TO hr_admin;

详细内容见:Oracle Common User 与 Local User


7. CDB 资源管理

7.1 资源分配

-- 创建 PDB 资源计划
EXEC DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
EXEC DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN(
  plan => 'cdb_plan',
  comment => 'CDB resource plan'
);

-- 配置 PDB 资源
EXEC DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE(
  plan => 'cdb_plan',
  pluggable_database => 'hrpdb',
  shares => 2,
  utilization_limit => 60,
  memory_limit => 40
);

EXEC DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE(
  plan => 'cdb_plan',
  pluggable_database => 'salespdb',
  shares => 3,
  utilization_limit => 80
);

EXEC DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();
EXEC DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();

-- 启用计划
ALTER SYSTEM SET resource_manager_plan='cdb_plan' SCOPE=BOTH;

7.2 内存管理

-- 设置 PDB 内存限制
ALTER SYSTEM SET sga_min_size=1G SCOPE=BOTH;
ALTER SYSTEM SET sga_target=4G SCOPE=BOTH;
ALTER SYSTEM SET pga_aggregate_limit=2G SCOPE=BOTH;
ALTER SYSTEM SET pga_aggregate_target=1G SCOPE=BOTH;

8. 监控 CDB/PDB

8.1 PDB 状态

SELECT 
  con_id, 
  name, 
  open_mode, 
  restricted
FROM v$pdbs;

8.2 PDB 资源使用

SELECT 
  p.name AS pdb_name,
  r.cpu_consumed_time,
  r.memory_used,
  r.cpu_utilization
FROM v$rsrc_pdb r, v$pdbs p
WHERE r.con_id = p.con_id;

8.3 PDB 历史信息

SELECT 
  name,
  open_time,
  close_time
FROM v$pdb_history
ORDER BY open_time DESC;

9. 多租户备份恢复

9.1 RMAN 备份 PDB

-- 备份单个 PDB
RMAN> BACKUP PLUGGABLE DATABASE hrpdb PLUS ARCHIVELOG;

-- 备份所有 PDB
RMAN> BACKUP PLUGGABLE DATABASE ALL PLUS ARCHIVELOG;

-- 备份 CDB
RMAN> BACKUP DATABASE PLUS ARCHIVELOG;

9.2 PDB 时间点恢复

-- 单个 PDB 时间点恢复
RMAN> ALTER PLUGGABLE DATABASE hrpdb CLOSE;
RMAN> RUN {
  SET UNTIL TIME "TO_DATE('2026-07-21 14:00:00','YYYY-MM-DD HH24:MI:SS')";
  RESTORE PLUGGABLE DATABASE hrpdb;
  RECOVER PLUGGABLE DATABASE hrpdb;
}
RMAN> ALTER PLUGGABLE DATABASE hrpdb OPEN RESETLOGS;

10. 常见坑与排错

10.1 ORA-65049: CDB 架构问题

现象:23ai 中创建非 CDB 失败。

原因:23ai 强制多租户。

修复:使用 CDB + PDB 架构。

10.2 PDB 启动未自动打开

现象:CDB 重启后 PDB 处于 MOUNT 状态。

修复

ALTER PLUGGABLE DATABASE hrpdb SAVE STATE;

10.3 ORA-65096: 无效 Common User 名

现象:创建 Common User 失败。

修复

-- Common User 必须以 c## 或 C## 开头
CREATE USER c##admin IDENTIFIED BY ******

10.4 ORA-01031: Common User 权限不足

现象:Common User 在 PDB 中无法操作。

修复

-- 授予 ALL 容器权限
GRANT CREATE SESSION TO c##admin CONTAINER=ALL;
GRANT CREATE TABLE TO c##admin CONTAINER=ALL;

10.5 PDB 插入失败 ORA-65016

现象:插入 PDB 时报 ORA-65016。

修复

-- 1. 生成 manifest
ALTER PLUGGABLE DATABASE hrpdb UNPLUG INTO '/tmp/hrpdb.xml';

-- 2. 检查兼容性
SET SERVEROUTPUT ON
DECLARE
  compatible BOOLEAN := FALSE;
BEGIN
  compatible := DBMS_PDB.CHECK_PLUG_COMPATIBILITY(
    pdb_descr_file => '/tmp/hrpdb.xml',
    pdb_name => 'hrpdb');
  IF compatible THEN
    DBMS_OUTPUT.PUT_LINE('Compatible');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Incompatible');
  END IF;
END;
/

-- 3. 处理不兼容项后插入
CREATE PLUGGABLE DATABASE hrpdb USING '/tmp/hrpdb.xml' NOCOPY;

11. 最佳实践

  1. 业务用 PDB 隔离:每个业务一个 PDB
  2. CDB 管理集中:一套 Oracle Home 管理
  3. PDB 备份独立:RMAN 单独备份
  4. 资源计划限制:避免 PDB 间资源争抢
  5. Common User 谨慎使用:仅管理用
  6. PDB SAVE STATE:避免手动打开
  7. 克隆开发环境:快速搭建
  8. Data Guard 备 PDB:主备库同步
  9. Application Container:SaaS 多租户
  10. 监控 PDB 资源:v$rsrc_pdb

12. 参考资料

[1] Oracle Multitenant Administrator’s Guide 19c https://docs.oracle.com/en/database/oracle/oracle-database/19/multi/

[2] Oracle Database Administrator’s Guide 19c, “Managing a Multitenant Environment” https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/