CDB 和 PDB
多租户体系结构使 Oracle 数据库能够充当多租户容器数据库 (container database,CDB)。
从 Oracle Database 21c 开始,仅支持多租户容器数据库。在以前的发行版中,Oracle 支持非容器数据库(非 CDB)。
-
关于 CDB 中的容器 容器是多租户容器数据库 (container database,CDB) 中方案、对象和相关结构的集合。在 CDB 中,每个容器都有一个唯一的 ID 和名称。
-
CDB 根和系统容器 CDB 根(也称为根)是所有 PDB 所属的方案、方案对象和非方案对象的集合。
-
PDB PDB 是用户创建的一组方案、对象和相关结构,在逻辑上作为单独的数据库显示在客户机应用程序中。
关于 CDB 中的容器
容器是多租户容器数据库 (Container Database,CDB) 中方案、对象和相关结构的集合。在 CDB 中,每个容器都有一个唯一的 ID 和名称。
CDB 包括零个、一个或许多客户创建的可插入数据库 (pluggable database,PDB) 和应用程序容器。PDB 是方案、方案对象和非方案对象的可移植集合,这些对象作为单独的数据库显示在 Oracle Net 客户机中。应用程序容器是用户创建的可选 CDB 组件,用于存储一个或多个应用程序后端的数据和元数据。CDB 包含零个或多个应用程序容器。
注:“应用程序容器”详细介绍了应用程序容器。
下图表示 CDB 中可能的容器。
图 1:CDB 中的容器

每个 CDB 都具有以下容器:
-
仅一个 CDB 根容器(也称为根)
CDB 根是所有 PDB 所属的方案、方案对象和非方案对象的集合(请参阅“ CDB 和 PDB ”)。根存储 Oracle 提供的元数据和公用用户。元数据的一个示例是 Oracle 提供的 PL/SQL 程序包的源代码。公用用户是每个容器中已知的数据库用户(请参阅“公用用户帐户”)。根容器名为
CDB$ROOT。 -
一个系统容器
系统容器包括根 CDB 和 CDB 中的所有 PDB。因此,系统容器是 CDB 本身的逻辑容器。
-
零个或多个应用程序容器
应用程序容器仅包含一个应用程序根,并且将 PDB 插入到此根。虽然系统容器包含 CDB 根和 CDB 内的所有 PDB,但应用程序容器仅包括插入到应用程序根中的 PDB。应用程序根属于 CDB 根,没有其他容器。
-
零个或多个用户创建的 PDB
PDB 包含一组特定功能所需的数据和代码(请参阅“ PDB ”)。例如,PDB 可以支持特定应用程序,例如人力资源或销售应用程序。创建 CDB 时不存在 PDB。可以根据业务需求添加 PDB。
PDB 恰好属于零个或一个应用程序容器。如果 PDB 属于应用程序容器,则它是应用程序 PDB 。例如,
cust1_pdb和cust2_pdb应用程序 PDB 可能属于saas_sales_ac应用程序容器,在这种情况下,它们不属于其他应用程序容器。应用程序种子是可选的应用程序 PDB,用作用户创建的 PDB 模板,使您能够快速创建新应用程序 PDB。 -
仅一个 seed PDB
种子 PDB 是系统提供的模板,CDB 可使用该模板创建新 PDB。种子 PDB 的名称为
PDB$SEED。不能在PDB$SEED中添加或修改对象。
示例 2-1 没有应用程序容器的 CDB
此示例显示一个包含五个容器的简单 CDB:系统容器(整个 CDB)、CDB 根、PDB 种子 (PDB$SEED) 和两个 PDB。每个 PDB 都有自己的专用应用程序。不同的 PDB 管理员管理每个 PDB。公用用户存在于具有单个身份的 CDB 中。在此示例中,公用用户 SYS 可以管理根和每个 PDB。在物理级别,此 CDB 由一个或多个数据库实例管理,并包含每个 PDB 和 CDB 本身的一组数据文件。
图 2:没有应用程序容器的 CDB

示例 2-2 包含应用程序容器的 CDB
在此变体中,CDB 包含一个名为 saas_sales_ac 的应用程序容器。在应用程序容器中,应用程序 PDB cust1_pdb 支持一个客户的应用程序,应用程序 PDB cust2_pdb 支持另一个客户的应用程序。CDB 还包含名为 hrpdb 的 PDB,该 PDB 支持 HR 应用程序,但不属于应用程序容器。
图 3:具有应用程序容器的 CDB

在本示例中,多个 DBA 管理 CDB 环境:
-
CDB 管理员自行管理 CDB。
-
应用程序容器管理员管理
saas_sales_ac容器,包括应用程序安装和升级。 -
应用程序 PDB 管理员管理
saas_sales_ac容器中的两个 PDB:cust1_pdb和cust2_pdb。 -
PDB 管理员负责管理
hrpdb。
CDB 根和系统容器
CDB 根(也称为根)是所有 PDB 所属的方案、方案对象和非方案对象的集合。
每个 CDB 都有一个且只有一个名为 CDB$ROOT 的根容器。根存储管理 PDB 所需的系统元数据。所有 PDB 都属于根。系统容器是 CDB 根和属于此根的所有 PDB。
CDB 根不存储用户数据。Oracle 建议您不要将公用对象添加到根中,也不要修改根中 Oracle 提供的方案。但是,您可以创建用于数据库管理的公用用户和角色。具有必要权限的公用用户可以在容器之间切换。
Oracle 建议使用 AL32UTF8 作为根字符集。具有不同字符集的 PDB 可以位于同一 CDB 中,而无需转换字符集。
示例 2-3 CDB 中的所有容器
以下查询由连接到 CDB 根的管理用户发出,列出 CDB 中的所有容器(包括种子和 CDB 根),顺序为 CON_ID。
COL NAME FORMAT A15
SELECT NAME, CON_ID, DBID, CON_UID, GUID
FROM V$CONTAINERS ORDER BY CON_ID;
NAME CON_ID DBID CON_UID GUID
------------- ------ ---------- ---------- --------------------------------
CDB$ROOT 1 1895287725 1 2003321EDD4F60D6E0534E40E40A41C5
PDB$SEED 2 2795386505 2795386505 200AC90679F07B55E05396C0E40A23FE
SAAS_SALES_AC 3 1239646423 1239646423 200B4CE0A8DC1D24E05396C0E40AF8EE
SALESPDB 4 3692549634 3692549634 200B4928319C1BCCE05396C0E40A2432
HRPDB 5 3784483090 3784483090 200B4928319D1BCCE05396C0E40A2432
另请参见:“公用用户账户”
PDB
PDB 是用户创建的一组方案、对象和相关结构,在逻辑上作为单独的数据库显示在客户机应用程序中。
每个 PDB 都归 SYS 所有,与创建 PDB 的用户无关。SYS 是 CDB 中的公用用户,这意味着该用户在根和 CDB 中的每个现有和将来的 PDB 中具有相同身份。
-
PDB 的类型所有 PDB 都由用户使用
CREATE PLUGGABLE DATABASE语句创建,但 Oracle 提供的PDB$SEED除外。 -
PDB 的用途 对于应用程序,PDB 是功能齐全的自包含 Oracle 数据库。您可以将 PDB 合并到单个 CDB 中,以实现规模经济,同时在 PDB 之间保持隔离。
-
代理 PDB 代理 PDB 指称为引用 PDB 的远程 PDB。
-
PDB 的名称 CDB 中的容器共享相同的名称空间,这意味着它们在此名称空间中必须具有唯一的名称。
-
PDB 之间的数据库链接默认情况下,连接到一个 PDB 的用户必须使用数据库链接来访问其他 PDB 中的对象。
PDB 的类型
所有 PDB 都使用 CREATE PLUGGABLE DATABASE 语句由用户创建,但 Oracle 提供的 PDB$SEED 除外。
可以创建以下类型的 PDB。
标准 PDB
此类型的 PDB 是运行 CREATE PLUGGABLE DATABASE(不将 PDB 指定为种子、代理 PDB 或应用程序根)的结果。其功能取决于在其中创建它的容器:
-
PDB 已插入到 CDB 根
此 PDB 属于 CDB 根容器,而不是应用程序容器。此类型的 PDB 不能使用应用程序公用对象。请参见“应用程序公用对象”。
-
应用程序 PDB
应用程序 PDB 仅属于一个应用程序容器。与插入到 CDB 根的 PDB 不同,应用程序 PDB 可以在应用程序容器内共享主应用程序定义。例如,应用程序根中的
usa_zipcodes表可能是数据链接的公用对象,这意味着它包含插入到此根的所有应用程序 PDB 可访问的数据。不位于应用程序容器的 PDB 无法访问其应用程序公用对象。
应用程序根
将应用程序根视为特定于应用程序的根容器。它用作应用程序后端主定义的存储库,包括公用数据和元数据。要创建应用程序根,请连接到 CDB 根并在 CREATE PLUGGABLE DATABASE 语句中指定 AS APPLICATION CONTAINER 子句。请参见“应用程序根”。
植入 PDB
与标准 PDB 不同,种子 PDB 不用于支持应用程序。相反,种子是用于创建支持应用程序的 PDB 的模板。种子可以是以下任一种子:
-
插入 CDB 根中的种子 PDB (
PDB$SEED)可以使用此系统提供的模板在应用程序容器或系统容器中创建新 PDB。系统容器仅包含一个 PDB 种子。不能删除
PDB$SEED,也不能向其中添加对象或修改对象。 -
应用程序种子 PDB
要加快在应用程序容器内创建应用程序 PDB 的速度,可以创建可选的应用程序种子。应用程序容器包含零个或一个应用程序种子。
通过连接到应用程序容器并执行
CREATE PLUGGABLE DATABASE ... AS SEED语句,可以创建应用程序种子。请参阅“应用程序种子”。
代理的 PDB
代理 PDB 是使用数据库链接引用远程 CDB 中 PDB 的 PDB 的 PDB。当 PDB 打开时,在代理 PDB 中发出语句时,该语句将在引用的 PDB 中执行。
连接到 CDB 根或应用程序根时,必须创建代理 PDB。可以更改或删除代理 PDB,就像更改或删除标准 PDB 一样。
PDB 的用途
对于应用程序,PDB 是功能齐全的自包含 Oracle 数据库。您可以将 PDB 合并到单个 CDB 中,以实现规模经济,同时在 PDB 之间保持隔离。
可以使用 PDB 实现以下特定目标:
-
存储特定于应用程序的数据
例如,销售应用程序可以有自己的专用 PDB,人力资源应用程序可以有自己的专用 PDB。或者,可以创建应用程序容器(PDB 的命名集合),以存储包含公用数据和元数据的应用程序后端。
-
将数据移动到其他 CDB 中
数据库是“可插入的”,因为您可以将其打包为自包含单元(称为断开的 PDB ),然后将其移动到另一个 CDB 中。
-
执行快速升级
可以在较低的 Oracle 数据库发行版中从 CDB 断开 PDB,然后在较高发行版中将其插入到 CDB 中。
-
快速复制数据,而不会造成可用性损失
为了进行测试和开发,可以在 PDB 保持打开状态时克隆 PDB,将克隆存储在同一或另一 CDB 中。(可选)可以将 PDB 指定为可刷新克隆 PDB 。或者,也可以使用 Oracle 提供的 seed PDB 或用户创建的应用程序种子来复制新 PDB。
-
引用其他 CDB 中的数据
可以创建引用不同 PDB 的代理 PDB ,该 PDB 位于同一 CDB 或单独的 CDB 中。在代理 PDB 中发出语句时,语句将在引用的 PDB 中执行。
-
在 PDB 内隔离授权
具有相应权限的本地或公用用户可以将方案对象的
EXECUTE权限授予单个 PDB 中的PUBLIC。
另请参见:
-
“关于应用程序容器”
-
Oracle AI Database Security Guide,了解如何在 CDB 中授予角色和权限
代理的 PDB
代理 PDB 指称为引用 PDB 的远程 PDB。
虽然您在代理(引用)PDB 中发出 SQL 语句,但这些语句在引用的 PDB 中执行。在这方面,代理 PDB 松散地类似于 Linux 中的符号链接文件。
代理 PDB 具有以下优势:
-
聚合来自多个应用模型的数据
使用代理 PDB,可以构建位置透明的应用程序,这些应用程序可以聚合来自多个源的数据。这些源可以位于同一数据中心,也可以分布在多个数据中心。
-
在一个 CDB 中启用应用程序根以将应用程序更改传播到其他应用程序根
假设 CDB
cdb_prod和cdb_test具有相同的应用程序模型。在cdb_prod的应用程序容器中创建代理 PDB,该代理 PDB 引用cdb_test中的应用程序根。在cdb_prod的应用程序根中运行安装和升级脚本时,Oracle AI Database 会将这些语句传播到代理 PDB,而代理 PDB 会将这些语句远程发送到cdb_test中的应用程序根。这样,cdb_test中的应用程序根将成为cdb_prod中应用程序根的副本。
要创建代理 PDB,请使用 AS PROXY FROM 子句执行 CREATE PLUGGABLE DATABASE,其中 FROM 指定引用的 PDB 名称和数据库链接。创建语句仅复制属于 SYSTEM 和 SYSAUX 表空间的数据文件。
示例 2-4 创建代理 PDB
此示例连接到本地生产 CDB 中的容器 saas_sales_ac。sales_admin 公用用户创建名为 sales_sync_pdb 的代理 PDB。此应用程序 PDB 在远程开发 CDB 中引用名为 saas_sales_test_ac 的应用程序根,该应用程序根使用 cdb_dev_rem 数据库链接进行访问。在生产 CDB 的 saas_sales_ac 中执行应用程序升级时,升级会自动传播到远程开发 CDB 中的应用程序根 saas_sales_test_ac。
CONNECT sales_admin@saas_sales_ac
Password: ***********
CREATE PLUGGABLE DATABASE sales_sync_pdb AS PROXY FROM saas_sales_test_ac@cdb_dev_rem;
PDB 的名称
CDB 中的容器共享相同的名称空间,这意味着它们在此名称空间中必须具有唯一的名称。
以下容器的名称不能在同一 CDB 内冲突:
-
CDB 根
-
插入到 CDB 根的 PDB
-
应用程序源
-
应用程序 PDB
例如,如果同一 CDB 包含应用程序容器 saas_sales_ac 和 saas_sales_test_ac,则两个名为 cust1 的应用程序 PDB 不能同时驻留在两个容器中。名称空间规则还阻止在 CDB 根中创建名为 cust1pdb 的 PDB,在应用程序根中创建名为 cust1pdb 的 PDB。
PDB 和应用程序根容器的名称必须遵循与网络服务名称相同的规则。此外,由于 PDB 或应用程序根具有具有自己的名称的服务,因此容器名称在通过特定监听程序公开其服务的所有 CDB 中必须唯一。用户创建的容器名称的第一个字符必须为字母,其余字符为字母数字或下划线 (_)。由于服务名称不区分大小写,因此容器名称不区分大小写,即使使用分隔符指定,也采用大写形式。
另请参阅: Oracle AI Database Net Services Reference(了解服务名的规则)
PDB 之间的数据库链接
默认情况下,连接到一个 PDB 的用户必须使用数据库链接来访问其他 PDB 中的对象。
图 4:PDB 之间的数据库链接

规则的例外包括:
-
数据链接公用对象,可供包含指向此对象的数据链接的所有应用程序 PDB 访问。例如,应用程序容器
saas_sales_ac可能在其应用程序中包含数据链接表usa_zipcodes。在这种情况下,公用 CDB 用户c##dba可以连接到此容器中的应用程序 PDB,然后查询usa_zipcodes,即使实际表位于应用程序根中也是如此。在这种情况下,不需要数据库链接。 -
从 CDB 根或应用程序根发出的 SQL 中的
CONTAINERS()子句。使用此子句,可以查询插入到容器根的所有 PDB 中的数据。
创建代理 PDB 时,必须在 CREATE PLUGGABLE DATABASE ... AS PROXY 语句的 FROM 子句中指定数据库链接名称。如果代理 PDB 和引用的 PDB 驻留在单独的 CDB 中,则必须在将包含代理 PDB 的 CDB 的根中定义数据库链接。数据库链接必须连接到远程引用的 PDB 或远程 CDB 的 CDB 根。
另请参见:“公用和本地对象”