3 Application Containers(3 应用程序容器)
本章介绍如何在 CDB 中创建应用程序容器,以在 PDB 之间共享应用程序数据和元数据,包含以下主题:
• About Application Containers(应用程序容器简介) • Application Common Objects(应用程序公用对象) • Container Maps(容器映射) • Cross-Container Operations(跨容器操作)
另请参见:
• ”Common and Local Objects“(公用对象与本地对象)了解应用程序公用对象
About Application Containers(应用程序容器简介)
应用程序容器 是一个可选的、由用户创建的 CDB 组件,用于存储一个或多个应用程序后端的数据和元数据。一个 CDB 可以包含零个或多个应用程序容器。
在应用程序容器内部,应用程序 是指存储在应用程序根中的命名的、版本化的公用数据和元数据集合。在应用程序容器的上下文中,”应用程序“一词指代”主应用程序定义“。例如,应用程序可能包括表、视图和包的定义。
例如,你可以在一个应用程序容器中创建多个与销售相关的 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 中相比,应用程序容器具有多项优势。• Application Container Use Case: SaaS(应用程序容器用例:SaaS)
SaaS 部署可以使用多个应用程序 PDB,每个 PDB 用于不同的客户,这些 PDB 共享元数据和数据。• Application Containers Use Case: Logical Data Warehouse(应用程序容器用例:逻辑数据仓库)
客户可以使用多个应用程序 PDB 来解决数据主权问题。
Key Benefits of Application Containers(应用程序容器的主要优势)
与将每个应用程序存储在单独的 PDB 中相比,应用程序容器具有多项优势。
• 应用程序根存储所有应用程序 PDB 都可以共享的元数据和数据。
例如,所有应用程序 PDB 可以共享中心表(例如列出默认应用程序角色的表)中的数据。此外,所有 PDB 可以共享一个表定义,并向其中添加特定于 PDB 的行。• 你可以在应用程序根中维护主应用程序定义,而无需在每个 PDB 中维护单独的副本。
如果在应用程序根中升级应用程序,则所做的更改会自动传播到所有应用程序 PDB。例如,应用程序后端可能包含数据链接的公用对象app_roles,这是一个列出默认角色(如admin、manager、sales_rep等)的表。连接到任何应用程序 PDB 的用户都可以查询此表。• 应用程序容器可以包含一个应用程序种子、多个应用程序 PDB 以及代理 PDB(引用其他 CDB 中的 PDB)。 • 你可以从应用程序种子快速创建新的应用程序 PDB。 • 你可以查询报告应用程序容器中所有 PDB 的视图。 • 当连接到应用程序根时,可以使用 CONTAINERS函数对多个 PDB 中的对象执行 DML 操作。
例如,如果products表存在于每个应用程序 PDB 中,则可以连接到应用程序根,使用一条SELECT语句查询所有应用程序 PDB 中的产品。• 你可以将 PDB 从应用程序根中拔出,然后将其插入到更高 Oracle 数据库版本的应用程序根中。因此,PDB 在 Oracle 数据库升级中非常有用。
Application Container Use Case: SaaS(应用程序容器用例:SaaS)
SaaS 部署可以使用多个应用程序 PDB,每个 PDB 用于不同的客户,这些 PDB 共享元数据和数据。
在纯 SaaS 环境中,主应用程序定义驻留在应用程序根中,而特定于客户的数据则驻留在其各自的应用程序 PDB 中。例如,sales_app 是应用程序根中的应用程序模型。名为 cust1_pdb 的应用程序 PDB 只包含客户 1 的销售数据,而名为 cust2_pdb 的应用程序 PDB 只包含客户 2 的销售数据。拔出、插入、克隆以及其他的 PDB 级操作都可用于单独的客户 PDB。

纯 SaaS 配置具有以下优点:
• 性能 • 安全性 • 支持多客户
每个客户的数据都驻留在其自己的容器中,但可以进行整合,以便你可以集中管理众多客户。这种模式将“将多个作为一个进行管理”的规模经济效应从 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 一样连接到应用程序根。
应用程序根与 CDB 根和标准 PDB 的不同之处在于,它可以存储由用户创建的公用对象,这些对象称为应用程序公用对象。插入应用程序根的应用程序 PDB 可以访问应用程序公用对象。应用程序公用对象对 CDB 根、其他应用程序根或不属于该应用程序根的 PDB 不可见。
Example 3-1 Creating an Application Root(示例 3-1:创建应用程序根)
在此示例中,你以管理公用用户 c##system 的身份登录到 CDB 根。创建一个名为 saas_sales_ac 的应用程序容器,然后打开同名的应用程序根。
-- Create the application container called saas_sales_ac
CREATE PLUGGABLE DATABASE saas_sales_ac AS APPLICATION CONTAINER
ADMIN USER saas_sales_ac_adm IDENTIFIED BY manager;
-- Open the application root
ALTER PLUGGABLE DATABASE saas_sales_ac OPEN;将当前容器设置为 saas_sales_ac,然后验证此容器是否为应用程序根:
-- Set the current container to 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©)在应用程序根中,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
---
YESApplication 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。但是,应用程序 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(应用程序公用对象)
应用程序公用对象 是在应用程序根中的应用程序内创建的公用对象。公用对象可以是数据链接的,也可以是元数据链接的。
对于数据链接的公用对象,应用程序 PDB 共享单一的数据集。例如,saas_sales_ac 应用程序容器的应用程序名为 saas_sales_app,版本为 1.0,并包含一个数据链接的 usa_zipcodes 表。在这种情况下,行在应用程序根中的表中存储一次,但在所有应用程序 PDB 中均可见。
对于元数据链接的公用对象,应用程序 PDB 仅共享元数据,但包含不同的数据集。例如,一个元数据链接的 products 表在每个应用程序 PDB 中具有相同的定义,但行本身是特定于 PDB 的。名为 cust1pdb 的应用程序 PDB 可能有一个包含图书的 products 表,而名为 cust2pdb 的应用程序 PDB 可能有一个包含汽车零部件的 products 表。
• About Commonality in a CDB(CDB 中的公用性)
在 CDB 或应用程序根中定义的公用现象,在插入到该根的所有容器中都是相同的。• Creation of Application Common Objects(创建应用程序公用对象)
要创建公用对象,请连接到应用程序根,然后执行指定了共享属性的CREATE语句。• Metadata-Linked Application Common Objects(元数据链接的应用程序公用对象)
元数据链接是一个数据字典对象,它支持引用应用程序容器中所有 PDB 共享的公用元数据,并向其授予权限。• Data-Linked Application Common Objects(数据链接的应用程序公用对象)
数据链接对象 是一种其元数据和数据都驻留在应用程序根中,并且可从该应用程序容器中的所有应用程序 PDB 进行访问的对象。• Extended Data-Linked Application Objects(扩展数据链接的应用程序对象)
扩展数据链接对象 是数据链接对象和元数据链接对象的混合体。
另请参见:
• ”Common and Local Objects“(公用对象与本地对象)了解公用对象
About Commonality in a CDB(CDB 中的公用性)
在 CDB 或应用程序根中定义的公用现象,在插入到该根的所有容器中都是相同的。
• Principles of Commonality(公用性原则)
在 CDB 中,一个现象可以在系统容器(CDB 本身)内是公用的,也可以在特定的应用程序容器内是公用的。• Namespaces 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 中。
上述原则对本地现象和公用现象都有影响。
本地现象
本地现象在一个容器内必须唯一命名,但在 CDB 中跨所有容器不需要唯一。不同容器中同名的本地现象是不同的。例如,一个 PDB 中的本地用户 sh 与另一个 PDB 中的本地用户 sh 没有冲突。
CDB$ROOT 公用现象
在 CDB$ROOT 中定义的公用现象存在于多个容器中,并且在每个命名空间内必须唯一。例如,CDB 根包含预定义的公用用户,如 SYSTEM 和 SYS。为了确保命名空间隔离,Oracle AI Database 会阻止在另一个容器中创建 SYSTEM 用户。
为了确保命名空间隔离,在 CDB 根中由用户创建的公用现象的名称必须以 COMMON_USER_PREFIX 初始化参数指定的值开头。默认前缀是 c## 或 C##。所有其他由用户创建的现象的名称不得以 c## 或 C## 开头。例如,你不能在 hrpdb 中创建名为 c##hr 的本地用户,也不能在 CDB 根中创建名为 hr 的公用用户。
应用程序公用现象
在应用程序容器内,本地现象和应用程序公用现象的名称不能冲突。
• 应用程序公用用户和角色
应用程序公用用户遵循与 CDB 公用用户相同的原则。区别在于,对于 CDB 公用用户,公用用户前缀的默认值是c##或C##,而在应用程序根中,公用用户前缀的默认值是空字符串。
多租户架构假定你从应用程序根创建应用程序 PDB,或者将单租户应用程序转换为多租户应用程序。• 应用程序公用对象
多租户架构假定你在应用程序根中创建应用程序公用对象。之后,在应用程序 PDB 中本地添加数据。但是,Oracle AI Database 支持在应用程序 PDB 内创建本地表。在这种情况下,本地表与应用程序 PDB 中的应用程序公用对象位于同一命名空间中。
另请参见:
• 《Oracle AI Database Security Guide》(《Oracle AI Database 安全指南》),了解有关公用用户和角色的更多信息
Creation of Application Common Objects(创建应用程序公用对象)
要创建公用对象,请连接到应用程序根,然后执行指定了共享属性的 CREATE 语句。
你只能在应用程序安装、升级或打补丁期间创建或更改应用程序公用对象。可以通过以下方式指定共享属性:
• DEFAULT_SHARING初始化参数
该设置是在根中创建的所有受支持类型的数据库对象的默认共享属性。• SHARING子句
你在CREATE语句中直接指定此子句。当 SQL 语句中包含SHARING子句时,它将优先于DEFAULT_SHARING初始化参数中指定的值。可能的值为METADATA、DATA、EXTENDED DATA和NONE。
下表展示了应用程序公用对象的类型,以及数据和元数据的存储位置。
Table 3-1 Application Common Objects(表 3-1 应用程序公用对象)
另请参见:
• 《Oracle AI Database Security Guide》(《Oracle AI Database 安全指南》),了解如何管理公用对象的权限
Metadata-Linked Application Common Objects(元数据链接的应用程序公用对象)
元数据链接是一个数据字典对象,它支持引用应用程序容器中所有 PDB 共享的公用元数据,并向其授予权限。
在 SHARING 子句或 DEFAULT_SHARING 初始化参数中指定 METADATA 值,将指定一个指向对象元数据的链接,这称为元数据链接的公用对象。该对象的元数据在应用程序根中存储一次。
表、视图和代码对象(如 PL/SQL 过程)可以共享元数据。在此上下文中,“元数据”包括列定义、约束、触发器和代码。例如,如果 sales_mlt 是一个元数据链接的公用表,那么所有应用程序 PDB 都通过元数据链接访问存储于应用程序根中的该表的相同定义。sales_mlt 中的行在每个应用程序 PDB 中都不同,但列定义是相同的。
通常,应用程序中的大多数对象都是元数据链接的。因此,你只需要维护一个主应用程序定义。这种方法将多个应用程序 PDB 中应用程序的管理集中化。
Example 3-2 Creating a Metadata-Linked Common Object(示例 3-2:创建元数据链接的公用对象)
在此示例中,SYSTEM 用户登录到 saas_sales_ac 应用程序容器。SYSTEM 安装一个名为 saas_sales_app、版本为 1.0 的应用程序。此应用程序创建一个名为 saas_sales_adm 的公用用户账户。该模式包含一个名为 sales_mlt 的元数据链接公用表。
-- Begin the install of saas_sales_app
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app BEGIN INSTALL ©1.0©;
-- Create the tablespace for the app
CREATE TABLESPACE saas_sales_tbs DATAFILE SIZE 100M AUTOEXTEND ON NEXT 10M
MAXSIZE 200M;
-- Create the user account saas_sales_adm, which will own the app
CREATEUSER saas_sales_adm IDENTIFIED BY****** CONTAINER=ALL;
-- Grant necessary privileges to this user account
GRANTCREATE SESSION, DBA TO saas_sales_adm;
-- Makes the tablespace that you just created the default for saas_sales_adm
ALTERUSER saas_sales_adm DEFAULT TABLESPACE saas_sales_tbs;
-- Now connect as the application owner
CONNECT saas_sales_adm/******@saas_sales_ac
-- Create a metadata-linked table
CREATE TABLE saas_sales_adm.sales_mlt SHARING=METADATA
(YEAR NUMBER(4),
REGION VARCHAR2(10),
QUARTER VARCHAR2(4),
REVENUE NUMBER);
-- End the application installation
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的 PDB 中sales_mlt的中间层代码会将行添加到cust1_pdb中的该表,而更新cust2_pdb中sales_mlt的中间层代码会将行添加到cust2_pdb 中该表的副本。只有存储在应用程序根中的表元数据是共享的。
注意:有关公用授予的对象权限如何工作的更多信息,请参阅《Oracle AI Database Security Guide》(《Oracle AI Database 安全指南》)。
• Metadata Links(元数据链接)
对于元数据链接的应用程序公用对象,对象的元数据在应用程序根中存储一次。元数据链接是一种字典对象,其对象类型与它所共享的元数据相同。
Metadata Links(元数据链接)
对于元数据链接的应用程序公用对象,对象的元数据在应用程序根中存储一次。元数据链接是一种字典对象,其对象类型与它所共享的元数据相同。
元数据链接的描述存储在创建它的 PDB 的数据字典中。元数据链接必须由应用程序公用用户拥有。你只能使用元数据链接来共享由其创建者在 CDB 根或应用程序根中拥有的公用对象的元数据。
与数据链接不同,元数据链接仅依赖于公用数据。例如,如果应用程序在应用程序根中包含本地表 dow_close_lt 和 nasdaq_close_lt,则公用用户无法创建指向这些对象的元数据链接。但是,一个名为 sales_mlt 的应用程序公用表可以被元数据链接。
如果具有权限的公用用户更改了 sales_mlt 的元数据,例如向表中添加一列,则此更改将传播到元数据链接。应用程序 PDB 用户不得更改元数据链接中的元数据。例如,仅管理名为 cust1_pdb 的应用程序 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 应用程序容器。SYSTEM 将名为 saas_sales_app 的应用程序从版本 1.0 升级到 2.0。此应用程序升级以公用用户 saas_sales_adm 的身份登录到容器,创建一个名为 countries_dlt 的数据链接表,然后向其中插入行。
-- Begin an upgrade of the application
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app BEGIN UPGRADE ©1.0© to
©2.0©;
-- Connect as application owner to application root
CONNECT saas_sales_adm/manager@saas_sales_ac
-- Create data-linked table named countries_dlt
CREATE TABLE countries_dlt SHARING=DATA
(country_id NUMBER,
country_name VARCHAR2(20));
-- Insert records into 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©);
-- End application upgrade
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。所有应用程序 PDB 都需要美国的邮政编码。在这种情况下,你可以在应用程序根中创建一个 zipcodes_edt 扩展数据链接表。应用程序根存储了美国的邮政编码,因此所有应用程序 PDB 都可以访问它们。但是,某个应用程序 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 的扩展数据链接表,然后向其中插入行。
-- Begin an upgrade of the app
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app BEGIN UPGRADE ©2.0© to
©3.0©;
-- Connect as app owner to app root
CONNECT saas_sales_adm/manager@saas_sales_ac
-- Create a common-data table named zipcodes_edt
CREATE TABLE zipcodes_edt SHARING=EXTENDED DATA
(code VARCHAR2(5),
country_id NUMBER,
region VARCHAR2(10));
-- Load rows into 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;
-- End app upgrade
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。
映射表指定元数据链接公用表中的列,并使用分区将不同的应用程序 PDB 与不同的列值关联起来。通过这种方式,当数据在表级别没有物理分区时,容器映射允许在 PDB 级别对数据进行分区。
使用容器映射的关键组件如下:
• 元数据链接表
此表旨在使用容器映射进行查询。例如,你可以创建一个名为countries_mlt的元数据链接表,该表在每个应用程序 PDB 中存储不同的数据。在amer_pdb中,countries_mlt.cname列存储北美国家名称;在euro_pdb中,countries_mlt.cname列存储欧洲国家名称;在asia_pdb中,countries_mlt.cname列存储亚洲国家名称。• 映射表
在应用程序根中,你创建一个按列表、哈希或范围分区的单列映射表。该映射表允许使用容器映射所启用的分区策略来查询元数据链接表。映射对象表中的分区名称必须与应用程序容器中应用程序 PDB 的名称相匹配。
例如,名为pdb_map_tbl的映射表可以在cname列上按列表分区。分区名为amer_pdb、euro_pdb和asia_pdb,这些名称与应用程序 PDB 的名称相对应。每个分区中的值是国家的名称,例如PARTITION amer_pdb VALUES (©US©,©MEXICO©,©CANADA©)。
从 Oracle Database 18c 开始,对于使用映射的CONTAINERS()查询,映射表中的分区列不需要与元数据链接表中的列相匹配。假设表sh.sales已为容器映射pdb_map_tbl启用,并且cname是映射表的分区列。即使sh.sales不包含cname列,映射表也会将以下查询路由到适当的 PDB:SELECT * FROM CONTAINERS(sh.sales) WHERE cname = ©US© ORDER BY time_id。• 容器映射
容器映射是指定映射表的数据库属性。要设置该属性,请连接到应用程序根并执行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 部分)
在此示例中,你以应用程序管理员的身份登录到应用程序根。假设一个应用程序容器有三个应用程序 PDB:amer_pdb、euro_pdb 和 asia_pdb。每个应用程序 PDB 存储不同区域的国家名称。一个名为 oe.countries_mlt 的元数据链接表有一个 cname 列用于存储国家名称。针对此分区策略,你使用列表分区创建一个名为 salesadm.pdb_map_tbl 的映射对象,为每个区域创建一个分区。国家名称决定区域。
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app BEGIN INSTALL ©1.0©;
-- Create the metadata-linked table.
CREATE TABLE oe.countries_mlt SHARING=METADATA (
region VARCHAR2(30),
cname VARCHAR2(30));
-- Create the partitioned map table, which is list partitioned on the
-- cname column. The names of the partitions are the names of the
-- application PDBs.
CREATE TABLE salesadm.pdb_map_tbl (cname VARCHAR2(30) NOT NULL)
PARTITIONBY LIST (cname) (
PARTITION amer_pdb VALUES (©US©,©MEXICO©,©CANADA©),
PARTITION euro_pdb VALUES (©UK©,©FRANCE©,©GERMANY©),
PARTITION asia_pdb VALUES (©INDIA©,©CHINA©,©JAPAN©));
-- Set the CONTAINER_MAP database property to the map object.
ALTER PLUGGABLE DATABASE SET CONTAINER_MAP=©salesadm.pdb_map_tbl©;
-- Enable the container map for the metadata-linked table to be queried.
ALTER TABLE oe.countries_mlt ENABLE CONTAINER_MAP;
-- Ensure that the table to be queried is enabled for the
-- CONTAINERS clause.
ALTER TABLE oe.countries_mlt ENABLE CONTAINERS_DEFAULT;
-- End the application installation.
ALTER PLUGGABLE DATABASE APPLICATION saas_sales_app END INSTALL ©1.0©;注意:尽管你使用分区语法创建容器映射,但数据库并不会使用分区功能。定义容器映射不需要 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 的数据。
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;
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;
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 列返回正确的值。
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
------
ASIACross-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 的应用程序容器中。你可以以管理员身份连接到应用程序根,并按如下方式执行更新:
CONNECT sales_admin@saas_sales_ac
Password: *******
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“(公用用户账户)
夜雨聆风