Oracle官方文档翻译《Database Concepts 23ai》第3章-应用程序容器
Oracle官方文档翻译《Database Concepts 23ai》第3章-应用程序容器
3 Application Containers(3 应用程序容器)
在容器数据库(CDB)中,可创建用于存储应用程序数据和元数据的容器,该容器可由多个可插入数据库(PDB)共享。
About Application Containers(应用程序容器简介)
应用程序容器是 CDB 中可选的、用户创建的组件,用于存储一个或多个应用程序后端的数据和元数据。一个 CDB 可包含零个或多个应用程序容器。
在应用程序容器内,“应用程序”指存储在应用程序根容器中的、具有名称和版本的公用数据及元数据集合。在此语境下,“应用程序”即“主应用程序定义”,例如,应用程序可能包含表、视图和包的定义。
例如,可在一个应用程序容器内创建多个与销售相关的 PDB,这些 PDB 共享由一组公用表和表定义构成的应用程序;也可在另一个独立的应用程序容器内存储多个与人力资源相关的 PDB,这些 PDB 拥有各自的公用表和表定义。
通过带有 AS APPLICATION CONTAINER
子句的 CREATE PLUGGABLE DATABASE
语句,可创建应用程序容器的应用程序根容器,进而隐式创建应用程序容器本身。首次创建应用程序容器时,其中不包含任何 PDB;若要创建应用程序 PDB,需先连接到应用程序根容器,再执行 CREATE PLUGGABLE DATABASE
语句。
在 CREATE PLUGGABLE DATABASE
语句中,必须指定容器名称(与应用程序根容器名称相同),例如 saas_sales_ac
。应用程序容器名称在以下范围内必须唯一:
- 所属 CDB 内部;
- 可通过特定监听器访问其实例的所有 CDB 范围内。
每个应用程序容器都有一个默认服务,该服务名称与应用程序容器名称相同。
Purpose of Application Containers(应用程序容器的用途)
在某些方面,应用程序容器相当于 CDB 内部的“应用程序专用 CDB”。与 CDB 本身类似,应用程序容器可包含多个 PDB,并支持这些 PDB 共享元数据和数据。
Application Root(应用程序根容器)
一个应用程序容器恰好包含一个应用程序根容器,该根容器是容器内所有应用程序 PDB 的父容器。
Application PDBs(应用程序 PDB)
应用程序 PDB 是驻留在应用程序容器内的 PDB。CDB 中的每个 PDB 最多属于一个应用程序容器。
Application Seed(应用程序种子)
应用程序种子是应用程序容器内可选的、用户创建的 PDB。一个应用程序容器包含零个或一个应用程序种子。
Purpose of Application Containers(应用程序容器的用途)
在某些方面,应用程序容器相当于 CDB 内部的“应用程序专用 CDB”。与 CDB 本身类似,应用程序容器可包含多个 PDB,并支持这些 PDB 共享元数据和数据。
应用程序根容器支持应用程序 PDB 共享一个应用程序(在此语境下,指具有名称和版本的公用元数据及数据集合)。典型的应用程序会安装应用程序公用用户、元数据链接公用对象和数据链接公用对象。
Key Benefits of Application Containers(应用程序容器的主要优势)
与将每个应用程序存储在独立 PDB 中相比,应用程序容器具有多项优势:
- 应用程序根容器存储所有应用程序 PDB 可共享的元数据和数据。
例如,所有应用程序 PDB 可共享中心表(如列出默认应用程序角色的表)中的数据,也可共享表定义并向其中添加 PDB 专用行。 - 仅需在应用程序根容器中维护主应用程序定义,无需在每个 PDB 中维护单独副本。
若在应用程序根容器中升级应用程序,更改会自动传播到所有应用程序 PDB。例如,应用程序后端可能包含数据链接公用对象app_roles
(列出admin
、manager
、sales_rep
等默认角色的表),连接到任何应用程序 PDB 的用户都可查询该表。 - 应用程序容器可包含应用程序种子、应用程序 PDB 和代理 PDB(引用其他 CDB 中的 PDB):
- 可从应用程序种子快速创建新的应用程序 PDB;
- 可查询报告应用程序容器内所有 PDB 信息的视图;
- 连接到应用程序根容器时,可使用
CONTAINERS
函数对多个 PDB 中的对象执行 DML 操作。
例如,若每个应用程序 PDB 中都存在products
表,连接到应用程序根容器后,可通过一条SELECT
语句查询所有应用程序 PDB 中的products
数据。 - 可将 PDB 从应用程序根容器中拔出,再插入到更高 Oracle 数据库版本的应用程序根容器中,因此 PDB 对 Oracle 数据库升级十分有用。
Application Container Use Case: SaaS(应用程序容器用例:软件即服务(SaaS))
SaaS 部署可使用多个应用程序 PDB(每个客户对应一个),这些 PDB 共享元数据和数据。
在纯 SaaS 环境中,主应用程序定义存储在应用程序根容器中,而客户专用数据存储在其自身的应用程序 PDB 中。例如,sales_app
是应用程序根容器中的应用程序模型,应用程序 PDB cust1_pdb
仅包含客户 1 的销售数据,应用程序 PDB cust2_pdb
仅包含客户 2 的销售数据。可对单个客户 PDB 执行拔出、插入、克隆等 PDB 级操作。
Figure 3-1 SaaS Use Case
纯 SaaS 配置具有以下优势:
- 性能(Performance):优化资源利用率,提升应用程序响应速度。
- 安全性(Security):客户数据隔离存储,保障数据安全。
- 多客户支持(Support for multiple customers):集中管理多个客户的应用程序环境,降低运维成本。
每个客户的数据存储在独立容器中,同时通过整合实现多客户的集中管理。这种模式不仅为数据库管理员(DBA),也为应用程序管理员提供了“多客户统一管理”的规模经济优势。
Application Containers Use Case: Logical Data Warehouse(应用程序容器用例:逻辑数据仓库)
客户可使用多个应用程序 PDB 解决数据主权问题。
在一个示例用例中,某公司将每个财务季度的专用数据存储在独立 PDB 中。例如,名为 sales_ac
的应用程序容器包含 q1_2016_pdb
、q2_2016_pdb
、q3_2016_pdb
和 q4_2016_pdb
,每个季度的交易数据存储在对应季度的 PDB 中。若要生成年度业绩汇总报告,可使用 CONTAINERS()
子句跨四个 PDB 聚合数据。
这种逻辑数据仓库设计的优势包括:
- 针对单个 PDB 的数据抽取、转换和加载(ETL)操作不会影响其他 PDB;
- 执行计划更高效,因为计划基于实际数据分布生成。
Application Root(应用程序根容器)
一个应用程序容器恰好包含一个应用程序根容器,该根容器是容器内所有应用程序 PDB 的父容器。
应用程序根容器的属性在创建时确定,且无法更改。应用程序根容器仅属于 CDB 根容器,与 CDB 根容器和标准 PDB 既有相似之处,也有差异:
-
与 CDB 根容器的相似性
应用程序根容器可作为其下插入 PDB 的父容器。连接到应用程序根容器时,可执行以下操作:
管理公用用户和权限;
创建应用程序 PDB;
切换容器;
执行适用于应用程序容器内所有 PDB 的 DDL 语句。 -
与 PDB 的相似性
创建:通过CREATE PLUGGABLE DATABASE
语句创建;
修改:通过ALTER PLUGGABLE DATABASE
语句修改;
可用性控制:通过STARTUP
和SHUTDOWN
语句更改可用性;
其他操作:支持通过 DDL 语句执行插入、拔出和删除操作;
连接方式:拥有独立服务名,用户可像连接 PDB 一样连接应用程序根容器。
应用程序根容器可存储用户创建的公用对象(称为“应用程序公用对象”),这些对象仅对插入该应用程序根容器的应用程序 PDB 可见,对 CDB 根容器、其他应用程序根容器或不属于该应用程序根容器的 PDB 不可见。
Example 3-1 Creating an Application Root(示例 3-1:创建应用程序根容器)
本示例中,以管理员公用用户 c##system
登录到 CDB 根容器,创建名为 saas_sales_ac
的应用程序容器,然后打开与容器同名的应用程序根容器:
-- 创建名为 saas_sales_ac 的应用程序容器
CREATE PLUGGABLE DATABASE saas_sales_ac AS APPLICATION CONTAINER
ADMIN USER saas_sales_ac_adm IDENTIFIED BY manager;
-- 打开应用程序根容器
ALTER PLUGGABLE DATABASE saas_sales_ac OPEN;
将当前容器切换到 saas_sales_ac
,并验证该容器是否为应用程序根容器:
-- 将当前容器设置为 saas_sales_ac
ALTER SESSION SET CONTAINER = saas_sales_ac;
-- 格式化列显示
COL NAME FORMAT a15
COL ROOT FORMAT a4
-- 查询容器信息
SELECT CON_ID, NAME, APPLICATION_ROOT AS ROOT,
APPLICATION_PDB AS PDB
FROM V$CONTAINERS;
查询结果如下:
CON_ID | NAME | ROOT | PDB |
---|---|---|---|
3 | SAAS_SALES_AC | YES | NO |
对于应用程序容器,可在 SYS_CONTEXT
函数的 USERENV
命名空间中指定以下两个参数:
SYS_CONTEXT('USERENV', 'IS_APPLICATION_ROOT')
:判断当前容器是否为应用程序根容器;SYS_CONTEXT('USERENV', 'IS_APPLICATION_PDB')
:判断当前容器是否为应用程序 PDB。
在应用程序根容器中,SYS_CONTEXT('USERENV', 'IS_APPLICATION_ROOT')
的返回值如下:
SQL> select sys_context('USERENV', 'IS_APPLICATION_ROOT') from dual;
SYS_CONTEXT('USERENV','IS_APPLICATION_ROOT')
---------------------------------------------
YES
注意:SYS_CONTEXT('USERENV', 'IS_APPLICATION_ROOT')
的返回值与 V$PDBS
视图中的 APPLICATION_ROOT
列值一致:
SQL> select application_root from v$pdbs where
con_id=sys_context('USERENV', 'CON_ID');
APP
---
YES
Application PDBs(应用程序 PDB)
应用程序 PDB 是驻留在应用程序容器内的 PDB。CDB 中的每个 PDB 最多属于一个应用程序容器。
例如,saas_sales_ac
应用程序容器可能为多个客户提供支持,每个客户的应用程序将其数据存储在独立 PDB 中:
- 应用程序 PDB
cust1_sales_pdb
和cust2_sales_pdb
可能驻留在saas_sales_ac
中,且不再属于其他任何应用程序容器(但作为 PDB,它们必然也属于 CDB 根容器)。
创建应用程序 PDB 的方式:连接到应用程序根容器,执行 CREATE PLUGGABLE DATABASE
语句。可通过以下方式创建:
- 从种子 PDB 创建;
- 克隆现有 PDB;
- 插入已拔出的 PDB。
与插入 CDB 根容器的 PDB 类似,应用程序 PDB 支持克隆、拔出和删除操作,但必须始终属于某个应用程序根容器。
Application Seed(应用程序种子)
应用程序种子是应用程序容器内可选的、用户创建的 PDB。一个应用程序容器包含零个或一个应用程序种子。
应用程序种子支持快速创建应用程序 PDB,其在应用程序容器内的作用,与 PDB$SEED
在 CDB 内的作用相同。
应用程序种子的名称固定为 application_container_name$SEED
,其中 application_container_name
是应用程序容器的名称。例如,在 saas_sales_ac
应用程序容器中,可通过 CREATE PDB ... AS SEED
语句创建 saas_sales_ac$SEED
。
Application Common Objects(应用程序公用对象)
应用程序公用对象是在应用程序根容器的应用程序内创建的公用对象,分为数据链接(Data-Linked)和元数据链接(Metadata-Linked)两种类型。
- 数据链接公用对象:所有应用程序 PDB 共享同一组数据。例如,
saas_sales_ac
应用程序容器中的应用程序saas_sales_app
(版本 1.0)包含数据链接表usa_zipcodes
,该表的行仅在应用程序根容器中存储一次,但在所有应用程序 PDB 中均可见。 - 元数据链接公用对象:所有应用程序 PDB 仅共享元数据,数据则各自独立。例如,元数据链接表
products
在每个应用程序 PDB 中具有相同定义,但行数据为 PDB 专用:应用程序 PDBcust1pdb
的products
表可能存储图书数据,而cust2pdb
的products
表可能存储汽车零部件数据。
About Commonality in a CDB(CDB 中的公用性概述)
在 CDB 或应用程序根容器中定义的“公用现象”,在所有插入该根容器的子容器中保持一致。
Principles of Commonality(公用性原则)
在 CDB 中,“公用现象”的作用范围可分为两类:
- 系统容器(即 CDB 本身)范围内的公用;
- 特定应用程序容器范围内的公用。
例如:
- 连接到
CDB$ROOT
时创建的公用用户账户,对 CDB 内所有 PDB 和应用程序根容器均公用; - 连接到应用程序根容器时创建的应用程序公用用户账户,仅对该应用程序容器内的 PDB 公用。
在 CDB$ROOT
或应用程序根容器的语境下,公用性原则如下:
- 公用现象在所有现有和未来的子容器中保持一致。因此:
- 在 CDB 根容器中定义的公用用户,在所有插入该 CDB 根容器的 PDB 中具有相同身份;
- 在应用程序根容器中定义的公用用户,在所有插入该应用程序根容器的应用程序 PDB 中具有相同身份。
与之相反,“本地现象”的作用范围仅限于一个现有容器。
- 仅公用用户可修改公用现象的存在状态。更准确地说,仅登录到 CDB 根容器或应用程序根容器的公用用户,可创建、删除或修改当前容器范围内公用的用户、角色或对象的属性。
Namespaces in a CDB(CDB 中的命名空间)
在 CDB 中,每个对象的命名空间作用范围限定于其所属容器。
以下原则总结了命名空间的作用范围规则:
- 从应用程序视角看,每个 PDB 都是独立的数据库,与其他 PDB 完全区分;
- 本地现象在单个容器内创建,且作用范围限于该容器;
- 公用现象在 CDB 根容器或应用程序根容器中定义,且在所有已插入或将要插入该根容器的 PDB 中存在。
注意:在本主题中,“现象(phenomenon)”指“用户账户、角色或数据库对象”。
Local Phenomena(本地现象)
本地现象的名称仅需在所属容器内唯一,无需在 CDB 所有容器内唯一。不同容器中名称相同的本地现象是相互独立的。例如,一个 PDB 中的本地用户 sh
,与另一个 PDB 中的本地用户 sh
不冲突。
CDBROOTCommonPhenomena(CDBROOT Common Phenomena(CDBROOTCommonPhenomena(CDBROOT 中的公用现象)
在 CDB$ROOT
中定义的公用现象存在于多个容器中,且在每个容器的命名空间内必须唯一。例如,CDB 根容器包含 SYSTEM
、SYS
等预定义公用用户,为确保命名空间隔离,Oracle 数据库禁止在其他容器中创建 SYSTEM
用户。
为确保命名空间隔离,在 CDB 根容器中用户创建的公用现象,其名称必须以 COMMON_USER_PREFIX
初始化参数指定的值开头(默认前缀为 c##
或 C##
);其他用户创建的现象(非公用),其名称不得以 c##
或 C##
开头。例如:
- 无法在
hrpdb
中创建名为c##hr
的本地用户; - 无法在 CDB 根容器中创建名为
hr
的公用用户。
Application Common Phenomena(应用程序公用现象)
在应用程序容器内,本地现象和应用程序公用现象的名称不得冲突。
-
Application common users and roles(应用程序公用用户和角色)
应用程序公用用户的规则与 CDB 公用用户类似,区别在于:
CDB 公用用户的默认前缀为c##
或C##
;
应用程序根容器中公用用户的默认前缀为空字符串。
多租户体系结构假设:
从应用程序根容器创建应用程序 PDB;
或将单租户应用程序转换为多租户应用程序。 -
Application common objects(应用程序公用对象)
多租户体系结构假设在应用程序根容器中创建应用程序公用对象,之后在应用程序 PDB 中本地添加数据。但 Oracle 数据库也支持在应用程序 PDB 中创建本地表,此时本地表与应用程序公用对象在该应用程序 PDB 的同一命名空间内。
另请参见:《Oracle Database Security Guide》(《Oracle 数据库安全指南》),了解更多关于公用用户和角色的信息。
Creation of Application Common Objects(应用程序公用对象的创建)
创建公用对象时,需先连接到应用程序根容器,然后执行带有共享属性指定的 CREATE
语句。
仅可在应用程序的安装、升级或补丁操作过程中,创建或修改应用程序公用对象。可通过以下两种方式指定共享属性:
-
DEFAULT_SHARING 初始化参数
该参数设置为在根容器中创建的所有受支持类型数据库对象的默认共享属性。 -
SHARING 子句
在CREATE
语句中直接指定该子句。当 SQL 语句中包含SHARING
子句时,其优先级高于DEFAULT_SHARING
初始化参数的设置。该子句的可选值包括METADATA
(元数据链接)、DATA
(数据链接)、EXTENDED DATA
(扩展数据链接)和NONE
(不共享)。
下表列出了应用程序公用对象的类型,以及元数据和数据的存储位置:
Object Type(对象类型) | SHARING Value(SHARING 值) | Metadata Storage(元数据存储位置) | Data Storage(数据存储位置) |
---|---|---|---|
Data-Linked(数据链接) | DATA | Application root(应用程序根容器) | Application root(应用程序根容器) |
Extended Data-Linked(扩展数据链接) | EXTENDED DATA | Application root(应用程序根容器) | Application root and application PDB(应用程序根容器和应用程序 PDB) |
Metadata-Linked(元数据链接) | METADATA | Application root(应用程序根容器) | Application PDB(应用程序 PDB) |
另请参见:《Oracle Database Security Guide》(《Oracle 数据库安全指南》),了解如何管理公用对象的权限。
Metadata-Linked Application Common Objects(元数据链接应用程序公用对象)
元数据链接是一种数据字典对象,支持引用应用程序容器内所有 PDB 共享的公用元数据,并为其授予权限。
在 SHARING
子句或 DEFAULT_SHARING
初始化参数中指定 METADATA
值,即表示创建元数据链接公用对象(链接到对象的元数据)。对象的元数据仅在应用程序根容器中存储一次。
表、视图和代码对象(如 PL/SQL 过程)可共享元数据。在此语境下,“元数据”包括列定义、约束、触发器和代码。例如,若 sales_mlt
是元数据链接公用表,所有应用程序 PDB 都会通过元数据链接访问该表的定义(存储在应用程序根容器中);每个应用程序 PDB 中 sales_mlt
的行数据不同,但列定义相同。
通常,应用程序中的大多数对象都会采用元数据链接方式,因此仅需维护一个主应用程序定义,实现多应用程序 PDB 中应用程序的集中管理。
** Example 3-2 Creating a Metadata-Linked Common Object(示例 3-2:创建元数据链接公用对象)**
本示例中,SYSTEM
用户登录到 saas_sales_ac
应用程序容器,安装版本为 1.0 的应用程序 saas_sales_app
,创建名为 saas_sales_adm
的公用用户账户,并在该模式下创建元数据链接公用表 sales_mlt
:
-- 开始安装 saas_sales_app 应用程序
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app BEGIN INSTALL '1.0';
-- 为应用程序创建表空间
CREATE TABLESPACE saas_sales_tbs
DATAFILE SIZE 100M
AUTOEXTEND ON NEXT 10M
MAXSIZE 200M;
-- 创建应用程序所有者用户账户 saas_sales_adm
CREATE USER saas_sales_adm
IDENTIFIED BY ******
CONTAINER=ALL;
-- 为该用户账户授予必要权限
GRANT CREATE SESSION, DBA TO saas_sales_adm;
-- 将刚创建的表空间设为 saas_sales_adm 的默认表空间
ALTER USER saas_sales_adm DEFAULT TABLESPACE saas_sales_tbs;
-- 以应用程序所有者身份连接
CONNECT saas_sales_adm/******@saas_sales_ac
-- 创建元数据链接表
CREATE TABLE saas_sales_adm.sales_mlt
SHARING=METADATA
(
YEAR NUMBER(4),
REGION VARCHAR2(10),
QUARTER VARCHAR2(4),
REVENUE NUMBER
);
-- 结束应用程序安装
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app END INSTALL '1.0';
可通过 ALTER PLUGGABLE DATABASE APPLICATION ... SYNC
语句同步应用程序 PDB,使其使用相同的主应用程序定义。这样,每个应用程序 PDB 都会有一个指向 saas_sales_adm.sales_mlt
公用表的元数据链接:
- 在
cust1_pdb
中更新sales_mlt
的中间层代码,会向cust1_pdb
中的该表添加行; - 在
cust2_pdb
中更新sales_mlt
的中间层代码,会向cust2_pdb
中的该表添加行; - 仅存储在应用程序根容器中的表元数据是共享的。
注意:参见《Oracle Database Security Guide》(《Oracle 数据库安全指南》),了解公用授予的对象权限的工作原理。
Metadata Links(元数据链接)
对于元数据链接应用程序公用对象,其元数据仅在应用程序根容器中存储一次。元数据链接是一种数据字典对象,其对象类型与所共享的元数据的对象类型相同。
元数据链接的描述存储在其创建所在 PDB 的数据字典中,且必须由应用程序公用用户拥有。仅可使用元数据链接共享以下对象的元数据:
- 在 CDB 根容器或应用程序根容器中创建;
- 由创建者拥有;
- 属于公用对象。
与数据链接不同,元数据链接仅依赖公用数据。例如,若应用程序根容器中包含本地表 dow_close_lt
和 nasdaq_close_lt
,公用用户无法为这些对象创建元数据链接;但可为名为 sales_mlt
的应用程序公用表创建元数据链接。
若具有权限的公用用户修改 sales_mlt
的元数据(如添加列),该更改会传播到所有元数据链接。应用程序 PDB 的用户无法修改元数据链接中的元数据,例如,管理 cust1_pdb
的 DBA 无法仅在该 PDB 中为 sales_mlt
添加列——此类元数据更改仅可在应用程序根容器中执行。
Data-Linked Application Common Objects(数据链接应用程序公用对象)
数据链接对象是元数据和数据均存储在应用程序根容器中,且可被该应用程序容器内所有应用程序 PDB 访问的对象。
在 SHARING
子句或 DEFAULT_SHARING
初始化参数中指定 DATA
值,即表示创建数据链接公用对象(链接到公用对象)。数据仓库中的维度表通常适合作为数据链接公用表。
数据链接是一种数据字典对象,功能与同义词类似。例如,若 countries
是应用程序公用表,所有应用程序 PDB 都会通过数据链接访问该表的同一副本;若向该表添加一行,所有应用程序 PDB 均可看到该行。
数据链接必须由应用程序公用用户拥有,且从其所指向的对象继承对象类型。数据链接的描述存储在其创建所在 PDB 的数据字典中。例如,若一个应用程序容器包含 10 个应用程序 PDB,且每个 PDB 都包含指向 countries
应用程序公用表的链接,则这 10 个 PDB 的数据字典中均会包含该链接的定义。
Example 3-3 Creating a Data-Linked Object(示例 3-3:创建数据链接对象)
本示例中,SYSTEM
连接到 saas_sales_ac
应用程序容器,将应用程序 saas_sales_app
从版本 1.0 升级到 2.0;以公用用户 saas_sales_adm
身份登录,创建数据链接表 countries_dlt
并插入行:
-- 开始应用程序升级(从 1.0 到 2.0)
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app BEGIN UPGRADE
'1.0' to '2.0';
-- 以应用程序所有者身份连接到应用程序根容器
CONNECT saas_sales_adm/manager@saas_sales_ac
-- 创建名为 countries_dlt 的数据链接表
CREATE TABLE countries_dlt
SHARING=DATA
(
country_id NUMBER,
country_name VARCHAR2(20)
);
-- 向 countries_dlt 插入记录
INSERT INTO countries_dlt VALUES(1, 'USA');
INSERT INTO countries_dlt VALUES(44, 'UK');
INSERT INTO countries_dlt VALUES(86, 'China');
INSERT INTO countries_dlt VALUES(91, 'India');
-- 结束应用程序升级(升级到 2.0)
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app END UPGRADE TO '2.0';
通过 ALTER PLUGGABLE DATABASE APPLICATION ... SYNC
语句同步应用程序 PDB 与应用程序根容器,这样,每个已同步的应用程序 PDB 都会有一个指向 saas_sales_adm.countries_dlt
数据链接表的链接。
Extended Data-Linked Application Objects(扩展数据链接应用程序对象)
扩展数据链接对象是数据链接对象和元数据链接对象的混合类型。
在扩展数据链接对象中:
- 存储在应用程序根容器中的数据对所有应用程序 PDB 公用,且所有 PDB 均可访问;
- 每个应用程序 PDB 可在共享应用程序根容器公用数据的同时,创建自身的 PDB 专用数据,即通过自身数据补充公用数据。
例如,某销售应用程序可能支持多个应用程序 PDB,所有 PDB 都需要美国邮政编码数据:
- 在应用程序根容器中创建扩展数据链接表
zipcodes_edt
,存储美国邮政编码,供所有应用程序 PDB 访问; - 若某个应用程序 PDB 需要美国和加拿大的邮政编码数据,可在该 PDB 的扩展数据链接对象中存储加拿大邮政编码(而非存储在应用程序根容器中)。
创建扩展数据链接对象的方式:连接到应用程序根容器,在 CREATE
语句中指定 SHARING=EXTENDED DATA
关键字。
Example 3-4 Creating an Extended-Data Object(示例 3-4:创建扩展数据链接对象)
本示例中,SYSTEM
连接到 saas_sales_ac
应用程序容器,将应用程序 saas_sales_app
(示例 3-2 中创建)从版本 2.0 升级到 3.0;以公用用户 saas_sales_adm
身份登录,创建扩展数据链接表 zipcodes_edt
并插入行:
-- 开始应用程序升级(从 2.0 到 3.0)
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app BEGIN UPGRADE '2.0' to
'3.0';
-- 以应用程序所有者身份连接到应用程序根容器
CONNECT saas_sales_adm/manager@saas_sales_ac
-- 创建名为 zipcodes_edt 的公用数据表
CREATE TABLE zipcodes_edt
SHARING=EXTENDED DATA
(
code VARCHAR2(5),
country_id NUMBER,
region VARCHAR2(10)
);
-- 向 zipcodes_edt 加载行
INSERT INTO zipcodes_edt VALUES ('08820','1','East');
INSERT INTO zipcodes_edt VALUES ('10005','1','East');
INSERT INTO zipcodes_edt VALUES ('44332','1','North');
INSERT INTO zipcodes_edt VALUES ('94065','1','West');
INSERT INTO zipcodes_edt VALUES ('73301','1','South');
COMMIT;
-- 结束应用程序升级
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app END UPGRADE TO
'3.0';
通过 ALTER PLUGGABLE DATABASE APPLICATION ... SYNC
语句同步应用程序 PDB 与应用程序,这样,每个已同步的应用程序 PDB 都会有一个指向 saas_sales_adm.zipcodes_edt
数据链接表的链接:
- 连接到这些 PDB 的应用程序可查看应用程序升级期间插入到
zipcodes_edt
中的邮政编码; - 也可向该表插入自身的邮政编码数据。
Container Maps(容器映射)
容器映射支持连接到应用程序根容器的会话执行 SQL 语句,语句会根据 SQL 语句中谓词的值,路由到相应的 PDB。
映射表(Map Table)指定元数据链接公用表中的某一列,并通过分区将不同的应用程序 PDB 与不同的列值关联。通过这种方式,即使数据未在表级别进行物理分区,容器映射也能在 PDB 级别实现数据分区。
容器映射的关键组件
-
Metadata-linked table(元数据链接表)
该表旨在通过容器映射进行查询。例如,创建名为countries_mlt
的元数据链接表,每个应用程序 PDB 中存储不同数据:amer_pdb
的countries_mlt.cname
列存储北美国家名称;euro_pdb
的countries_mlt.cname
列存储欧洲国家名称;asia_pdb
的countries_mlt.cname
列存储亚洲国家名称。 -
Map table(映射表)
在应用程序根容器中创建单列映射表,支持按列表(List)、哈希(Hash)或范围(Range)分区。映射表使元数据链接表可通过容器映射启用的分区策略进行查询。映射表的分区名称必须与应用程序容器中的应用程序 PDB 名称一致。
例如,名为pdb_map_tbl
的映射表可能按cname
列进行列表分区,分区名称amer_pdb
、euro_pdb
、asia_pdb
与应用程序 PDB 名称对应,每个分区中的值为国家名称,如PARTITION amer_pdb VALUES ('US','MEXICO','CANADA')
(amer_pdb
分区包含“美国”“墨西哥”“加拿大”)。
从 Oracle 数据库 18c 开始,若要使CONTAINERS()
查询使用映射,映射表中的分区列无需与元数据链接表中的列匹配。假设sh.sales
表启用了容器映射pdb_map_tbl
,且cname
是映射表的分区列,即使sh.sales
表不包含cname
列,映射表仍会将以下查询路由到相应 PDB:
SELECT * FROM CONTAINERS(sh.sales) WHERE cname = 'US' ORDER BY time_id;
- Container map(容器映射)
容器映射是一种数据库属性,用于指定映射表。设置该属性的方式:连接到应用程序根容器,执行ALTER PLUGGABLE DATABASE SET CONTAINER_MAP=map_table
语句(map_table
为映射表名称)。
Example 3-5 Creating a Metadata-Linked Table, Map Table, and Container Map: Part 1(示例 3-5:创建元数据链接表、映射表和容器映射:第 1 部分)
-- 开始安装 saas_sales_app 应用程序(版本 1.0)
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app BEGIN INSTALL '1.0';
-- 创建元数据链接表
CREATE TABLE oe.countries_mlt
SHARING=METADATA
(
region VARCHAR2(30),
cname VARCHAR2(30)
);
-- 创建分区映射表(按 cname 列列表分区)
-- 分区名称与应用程序 PDB 名称一致
CREATE TABLE salesadm.pdb_map_tbl (cname VARCHAR2(30) NOT NULL)
PARTITION BY LIST (cname)
(
PARTITION amer_pdb VALUES ('US','MEXICO','CANADA'),
PARTITION euro_pdb VALUES ('UK','FRANCE','GERMANY'),
PARTITION asia_pdb VALUES ('INDIA','CHINA','JAPAN')
);
-- 设置 CONTAINER_MAP 数据库属性,指定映射表
ALTER PLUGGABLE DATABASE SET CONTAINER_MAP='salesadm.pdb_map_tbl';
-- 为元数据链接表启用容器映射,使其可被查询
ALTER TABLE oe.countries_mlt ENABLE CONTAINER_MAP;
-- 为元数据链接表启用 CONTAINERS 子句(默认查询需使用该子句)
ALTER TABLE oe.countries_mlt ENABLE CONTAINERS_DEFAULT;
-- 结束应用程序安装
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app END INSTALL '1.0';
本示例中,以应用程序管理员身份登录到应用程序根容器。假设应用程序容器包含三个应用程序 PDB:amer_pdb
、euro_pdb
和 asia_pdb
,每个 PDB 存储不同地区的国家名称。元数据链接表 oe.countries_mlt
包含存储国家名称的 cname
列,通过按列表分区创建映射表 salesadm.pdb_map_tbl
(为每个地区创建一个分区),由国家名称确定所属地区。
注意:尽管使用分区语法创建容器映射,但数据库不依赖分区功能,定义容器映射无需 Oracle 分区(Oracle Partitioning)组件。
上述脚本中,ALTER TABLE oe.countries_mlt ENABLE CONTAINERS_DEFAULT
语句指定:在应用程序根容器中执行的查询和 DML 语句,默认需对该数据库对象使用 CONTAINERS()
子句。
Example 3-6 Synchronizing the Application, and Adding Data: Part 2(示例 3-6:同步应用程序并添加数据:第 2 部分)
本示例承接上一示例,连接到应用程序根容器,依次切换到每个 PDB,同步 saas_sales_app
应用程序,并向 oe.countries_mlt
表添加 PDB 专用数据:
-- 切换到 amer_pdb
ALTER SESSION SET CONTAINER=amer_pdb;
-- 同步应用程序
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app SYNC;
-- 插入数据
INSERT INTO oe.countries_mlt VALUES ('AMER','US');
INSERT INTO oe.countries_mlt VALUES ('AMER','MEXICO');
INSERT INTO oe.countries_mlt VALUES ('AMER','CANADA');
COMMIT;
-- 切换到 euro_pdb
ALTER SESSION SET CONTAINER=euro_pdb;
-- 同步应用程序
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app SYNC;
-- 插入数据
INSERT INTO oe.countries_mlt VALUES ('EURO','UK');
INSERT INTO oe.countries_mlt VALUES ('EURO','FRANCE');
INSERT INTO oe.countries_mlt VALUES ('EURO','GERMANY');
COMMIT;
-- 切换到 asia_pdb
ALTER SESSION SET CONTAINER=asia_pdb;
-- 同步应用程序
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app SYNC;
-- 插入数据
INSERT INTO oe.countries_mlt VALUES ('ASIA','INDIA');
INSERT INTO oe.countries_mlt VALUES ('ASIA','CHINA');
INSERT INTO oe.countries_mlt VALUES ('ASIA','JAPAN');
COMMIT;
Example 3-7 Querying the Metadata-Linked Table: Part 3(示例 3-7:查询元数据链接表:第 3 部分)
本示例承接上一示例,连接到应用程序根容器,多次查询 oe.countries_mlt
表,在 WHERE
子句中指定不同国家,查询会返回 oe.countries_mlt.region
列的正确值:
-- 切换到应用程序根容器 saas_sales_ac
ALTER SESSION SET CONTAINER=saas_sales_ac;
-- 查询墨西哥对应的地区
SELECT region FROM oe.countries_mlt WHERE cname='MEXICO';
查询结果:
REGION
------
AMER
-- 查询德国对应的地区
SELECT region FROM oe.countries_mlt WHERE cname='GERMANY';
查询结果:
REGION
------
EURO
-- 查询日本对应的地区
SELECT region FROM oe.countries_mlt WHERE cname='JAPAN';
查询结果:
REGION
------
ASIA
Cross-Container Operations(跨容器操作)
跨容器操作是指同时影响多个容器的 DDL(数据定义语言)或 DML(数据操作语言)语句。
仅连接到 CDB 根容器或应用程序根容器的公用用户可执行跨容器操作。跨容器操作可影响以下对象:
- CDB 本身;
- CDB 内的多个容器;
- 在多个容器中存在的多个现象(如公用用户或公用角色);
- 执行 DDL 或 DML 语句的用户当前未连接的容器。
跨容器 DDL 操作示例包括:SYSTEM
用户向另一个公用用户公用授予权限;
适用于整个 CDB 的 ALTER DATABASE ... RECOVER
语句。
连接到 CDB 根容器或应用程序根容器时,可执行单条 DML 语句修改容器内多个 PDB 中的表或视图:
数据库通过 DML 语句中指定的 CON_ID
列值推断目标 PDB;
若未指定 CON_ID
,数据库使用 ALTER PLUGGABLE DATABASE CONTAINERS DEFAULT TARGET
语句指定的 CONTAINERS_DEFAULT_TARGET
属性值。
Example 3-8 Updating Multiple PDBs in a Single DML Statement(示例 3-8:通过单条 DML 语句更新多个 PDB)
本示例中,目标是将 sh.sales
表的 country_name
列值设置为 USA
。该表存在于两个独立 PDB 中(容器 ID 分别为 7 和 8),且这两个 PDB 均属于 saas_sales_ac
应用程序容器。以管理员身份连接到应用程序根容器,执行以下更新操作:
-- 以 sales_admin 身份连接到 saas_sales_ac
CONNECT sales_admin@saas_sales_ac
Password: *******
-- 更新两个 PDB 中的 sh.sales 表
UPDATE CONTAINERS(sh.sales) sal
SET sal.country_name = 'USA'
WHERE sal.CON_ID IN (7,8);
上述 UPDATE
语句中,sal
是 CONTAINERS(sh.sales)
的别名。
另请参见:“Common User Accounts”(公用用户账户)
更多推荐
所有评论(0)