容器是多租户容器数据库(CDB)中的模式、对象和相关结构的集合。在CDB中,每个容器都有唯一的ID和名称
This section contains the following topics:
- The CDB Root and System Container
The CDB root, also called simply the root, is a collection of schemas, schema objects, and nonschema objects to which all PDBs belong. - PDBs
A PDB is a user-created set of schemas, objects, and related structures that appears logically to a client application as a separate database. - Data Dictionary Architecture in a CDB
From the user and application perspective, the data dictionary in each container in a CDB is separate, as it would be in a non-CDB. - Current Container
For a given session, the current container is the one in which the session is running. The current container can be the CDB root, an application root, or a PDB. - Cross-Container Operations
A cross-container operation is a DDL or DML statement that affects multiple containers at once.
Parent topic: Overview of the Multitenant Architecture
2.1.1 The CDB Root and System Container
CDB根(也称为根)是所有PDBs所属的模式、模式对象和非模式对象的集合.
每个CDB都有且只有一个名为CDB$ root的根容器。根存储管理PDBs所需的系统元数据。所有PDBs都属于根目录。系统容器是CDB根和所有属于这个根的PDBs.
CDB根不存储用户数据。Oracle建议不要在根目录中添加公共对象或修改Oracle提供的模式。但是,您可以为数据库管理创建通用用户和角色。具有必要特权的普通用户可以在容器之间切换.
Oracle建议根字符集使用AL32UTF8。具有不同字符集的PDBs可以驻留在同一个CDB中,而不需要进行字符集转换.
Example 2-1 All Containers in a CDB
The following query, issued by an administrative user connected to the CDB root, lists all containers in the CDB (including the seed and CDB root), ordered by CON_ID
.
这个sql比较奇怪啊,刚开始我怎么只能查出来pdb,没出来cdb数据内容(试着创建了几个pdb后才出来)
SQL> COL NAME FORMAT A15
SQL> 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
See Also:
Parent topic: Overview of Containers in a CDB
2.1.2 PDBs
PDB是用户创建的一组模式、对象和相关结构,在客户端应用程序看来,它们逻辑上是独立的数据库.
Every PDB is owned by SYS
, regardless of which user created the PDB. SYS
is a common user in the CDB.
This section contains the following topics:
- Types of PDBs
All PDBs are user-created with theCREATE PLUGGABLE DATABASE
statement except forPDB$SEED
, which is Oracle-supplied. - Purpose of PDBs
From the point of view of an application, a PDB is a self-contained, fully functional Oracle database. You can consolidate PDBs into a single CDB to achieve economies of scale, while maintaining isolation between PDBs. - Proxy PDBs
A proxy PDB refers to a remote PDB, called the referenced PDB. - Names for PDBs
Containers in a CDB share the same namespace, which means that they must have unique names within this namespace. - Database Links Between PDBs
By default, a user connected to one PDB must use database links to access objects in a different PDB. This behavior is directly analogous to a user in a non-CDB accessing objects in a different non-CDB.
Parent topic: Overview of Containers in a CDB
2.1.2.1 Types of PDBs
除了由oracle提供的PDB$SEED之外,所有PDBs都是用户通过CREATE PLUGGABLE数据库语句创建的。
您可以创建以下类型的PDBs.
Standard PDB
这种类型的PDB在运行CREATE PLUGGABLE数据库时不会指定PDB作为种子、代理PDB或应用程序根。它的功能取决于创建它的容器:
-
PDB plugged in to the CDB root
这个PDB属于CDB根容器,而不是应用程序容器。这种类型的PDB不能使用应用程序公共对象。参见“应用程序公共对象”.
-
Application PDB
应用程序PDB恰好属于一个应用程序容器。与插入到CDB根目录的PDBs不同,应用程序PDBs可以在应用程序容器中共享主应用程序定义。例如,应用程序根目录中的usa_zipcodes表可能是一个数据链接的公共对象,这意味着它包含所有插入到这个根目录的应用程序PDBs可以访问的数据(这个应该是Application PDB区别于普通pdb数据库的优势所在)。不驻留在应用程序容器中的PDBs不能访问其应用程序公共对象。
可刷新的克隆PDB是源PDB的只读克隆,可以从源PDB接收增量更改。您可以配置克隆PDB来自动或仅手动接收更改.
快照复制PDB是使用存储级快照创建的。与标准的PDB克隆不同,快照复制PDB不能断开连接.
Application Root
将应用程序根作为特定于应用程序的根容器。它充当应用程序后端主定义(包括公共数据和元数据)的存储库。要创建应用程序根,请连接到CDB根,并在create PLUGGABLE数据库语句中指定AS application CONTAINER子句。看到“应用程序根”.
Seed PDBs
与标准PDB不同,种子PDB不打算支持应用程序。相反,种子是创建支持应用程序的PDBs的模板。种子可以是下列任何一种:
-
Seed PDB plugged in the CDB root (
PDB$SEED
)您可以使用这个系统提供的模板在应用程序容器或系统容器中创建新的PDBs。系统容器只包含一个PDB种子。您不能删除PDB$SEED,或向其中的对象添加对象或修改对象.
-
Application seed PDB
为了加速在应用程序容器中创建应用程序PDBs,您可以创建一个可选的应用程序种子。应用程序容器包含零个或一个应用程序种子.
You create an application seed by connecting to the application container and executing the
CREATE PLUGGABLE DATABASE ... AS SEED
statement. See "Application Seed".
Proxy PDBs
代理PDB是使用数据库链接引用远程CDB中的PDB的PDB。当PDB打开时在代理PDB中发出一条语句时,该语句在引用的PDB中执行.
在连接到CDB根或应用程序根时,必须创建一个代理PDB。您可以修改或删除代理PDB,就像您可以修改标准PDB一样.
See Also:
Parent topic: PDBs
2.1.2.2 Purpose of PDBs
从应用程序的角度来看,PDB是一个自包含的、功能完全的Oracle数据库。您可以将PDBs合并为一个单独的 CDB 节约资源, 同时保持PDBs之间的隔离。.
您可以使用PDBs来实现以下目标:
-
Store data specific to an application
例如,销售应用程序可以拥有自己的专用PDB,人力资源应用程序可以拥有自己的专用PDB。或者,您可以创建一个应用程序容器,它是一个命名的PDBs集合,用于存储包含公共数据和元数据的应用程序后端(请参阅“关于应用程序容器”).
-
Move data into a different CDB
数据库是“可插入的”,因为您可以将其打包为一个自包含的单元,称为不插电的PDB,然后将其移动到另一个CDB.
-
Perform rapid upgrades
可以在较低的Oracle数据库版本中从CDB中拔出PDB,然后在较高的版本中插入到CDB中.
-
Copy data quickly without loss of availability
对于测试和开发,您可以在PDB保持打开状态时克隆它,将克隆存储在相同或不同的CDB中。可选地,您可以将PDB指定为可刷新的克隆PDB。或者,您可以使用oracle提供的种子PDB或用户创建的应用程序种子来复制新的PDBs.
-
Reference data in a different CDB
您可以创建一个引用不同PDB的代理PDB,可以在同一个CDB中引用,也可以在单独的CDB中引用。当您在代理PDB中发出语句时,它们在引用的PDB中执行.
-
Isolate grants within PDBs
具有适当特权的本地或普通用户可以将模式对象上的执行特权授予单个PDB中的PUBLIC。
See Also:
-
Oracle Database Security Guide to learn how to grant roles and privileges in a CDB
Parent topic: PDBs
2.1.2.3 Proxy PDBs
A proxy PDB refers to a remote PDB, called the referenced PDB.
虽然在代理(引用)PDB中发出SQL语句,但是这些语句在引用的PDB中执行。在这方面,代理PDB大致类似于Linux中的符号链接文件.
代理PDBs提供了以下好处:
-
Aggregate data from multiple application models
代理PDBs使您能够构建位置透明的应用程序,可以聚合来自多个源的数据。这些源可以位于同一个数据中心,也可以分布在数据中心之间(比物化视图好,直接数据库层次的refresh).
-
Enable an application root in one CDB to propagate application changes to a different application root
假设CDBs cdb_prod和cdb_test具有相同的应用程序模型。在cdb_prod中的应用程序容器中创建一个代理PDB,它引用cdb_test中的应用程序根。当您在cdb_prod中的应用程序根中运行安装和升级脚本时,Oracle数据库将这些语句传播到代理PDB,后者将它们远程发送到cdb_test中的应用程序根。这样,cdb_test中的应用程序根就变成了cdb_prod中的应用程序根的副本。
要创建代理PDB,使用AS proxy from子句执行create PLUGGABLE数据库,其中FROM指定引用的PDB名称和数据库链接。创建语句只复制属于系统和SYSAUX表空间的数据文件.
Example 2-2 Creating a Proxy PDB
This example connects to the container saas_sales_ac
in a local production CDB. The sales_admin
common user creates a proxy PDB named sales_sync_pdb
. This application PDB references an application root named saas_sales_test_ac
in a remote development CDB, which it accesses using the cdb_dev_rem
database link. When an application upgrade occurs in saas_sales_ac
in the production CDB, the upgrade automatically propagates to the application root saas_sales_test_ac
in the remote development CDB.
CONNECT sales_admin@saas_sales_ac
Password: ***********
CREATE PLUGGABLE DATABASE sales_sync_pdb AS PROXY FROM saas_sales_test_ac@cdb_dev_rem;
Note:
Parent topic: PDBs
2.1.2.4 Names for PDBs
CDB中的容器共享同一个名称空间,这意味着它们必须在这个名称空间中具有惟一的名称。
下列容器的名称不得在同一国开行中发生冲突:
-
The CDB root
-
PDBs plugged in to the CDB root
-
Application roots
-
Application PDBs
例如,如果同一个CDB包含应用程序容器saas_sales_ac和saas_sales_test_ac,那么两个名为cust1的应用程序PDBs不能同时驻留在两个容器中。命名空间规则还防止在CDB根中创建名为cust1pdb的PDB,以及在应用程序根中创建名为cust1pdb的PDB。
PDBs和应用程序根容器必须遵循与服务名称相同的命名规则。此外,由于PDB或应用程序根具有具有自己名称的服务,因此容器名称必须在通过特定侦听器公开服务的所有CDBs之间是唯一的。用户创建的容器名称的第一个字符必须是字母数字,其余字符要么是字母数字,要么是下划线(_)。因为服务名不区分大小写,所以容器名不区分大小写,即使使用分隔符指定也用大写.
See Also:
-
Oracle Database Net Services Reference for the rules for service names
Parent topic: PDBs
2.1.2.5 Database Links Between PDBs
默认情况下,连接到一个PDB的用户必须使用数据库链接访问不同PDB中的对象。这种行为直接类似于非cdb中的用户访问另一个非cdb中的对象.(相当于物理隔绝的传统数据库之间的访问,只能通过dblink方式)
Figure 2-1 Database Link Between PDBs
在本例中,PDB管理员连接到名为hrpdb1的PDB。默认情况下,在此用户会话期间,c##dba无法在hrpdb2中查询emp2表,而无需指定数据库链接.
Description of "Figure 2-1 Database Link Between PDBs"
Exceptions to the rule include:
-
一个数据链接的公共对象,所有包含指向该对象的数据链接的应用程序PDBs都可以访问它。例如,应用程序容器saas_sales_ac可能在其应用程序中包含数据链接表usa_zipcodes。在这种情况下,CDB用户c##dba可以连接到这个容器中的应用程序PDB,然后查询usa_zipcodes,即使实际的表驻留在应用程序根目录中。在这种情况下,不需要数据库链接.
-
由CDB根或应用程序根发出的SQL中的CONTAINERS()子句。使用这个子句,您可以跨所有插入到根目录的PDBs查询数据。(这个得用例子跑一下,听不懂的):
SELECT * FROM CONTAINERS(sh.sales) ,我测试了一下,发现多了一个容器id
SQL> select * from CONTAINERS(sys.test);
A B CON_ID
---------- ---------- ----------
1 1 3
SQL> select * from (sys.test);
A B
---------- ----------
1 1
SQL> select con_id,name,open_mode,restricted from v$pdbs order by 1;
CON_ID NAME OPEN_MODE RESTRICTED
---------- ---------- ---------- ----------
3 ORCLPDB READ WRITE NO
在创建代理PDB时,必须在CREATE PLUGGABLE数据库的FROM子句中指定数据库链接名…作为代理声明。如果代理PDB和引用的PDB驻留在单独的CDBs中,那么数据库链接必须在包含代理PDB的CDB根中定义。数据库链接必须连接到远程引用的PDB或远程CDB的CDB根.
See Also:
-
"About PDB Administration" to learn how to access objects in other PDBs using database links
Parent topic: PDBs
2.1.3 CDB中的数据字典体系结构
从用户和应用程序的角度来看,CDB中每个容器中的数据字典是独立的,就像在非CDB中一样.
例如,每个PDB中的DBA_OBJECTS视图可以显示不同数量的行。这种字典分离使Oracle数据库能够分别管理PDBs和根目录.
This section contains the following topics:
- Purpose of Data Dictionary Separation
In a newly created non-CDB that does not yet contain user data, the data dictionary contains only system metadata. For example, theTAB$
table contains rows that describe only Oracle-supplied tables, for example,TRIGGER$
andSERVICE$
. - Metadata and Data Links
The CDB uses an internal linking mechanism to separate data dictionary information. - Container Data Objects in a CDB
A container data object is a table or view containing data pertaining to multiple containers or the whole CDB. - Data Dictionary Storage in a CDB
The data dictionary that stores the metadata for the CDB as a whole is stored only in the system tablespaces.
Parent topic: Overview of Containers in a CDB
2.1.3.1 Purpose of Data Dictionary Separation
在新创建的尚未包含用户数据的非cdb中,数据字典仅包含系统元数据。例如,选项卡$表包含只描述oracle提供的表的行,例如,触发器$和服务$。
下图描述了三个底层数据字典表,红色的条表示描述系统的行.
Figure 2-2 Unmixed Data Dictionary Metadata in a Non-CDB
Description of "Figure 2-2 Unmixed Data Dictionary Metadata in a Non-CDB"
如果用户在这个非cdb中创建自己的模式和表,那么数据字典现在包含一些描述oracle提供的实体的行,以及其他描述用户创建实体的行。例如,TAB$ dictionary表现在有一个描述员工的行和一个描述部门的行.
Figure 2-3 Mixed Data Dictionary Metadata in a Non-CDB
Description of "Figure 2-3 Mixed Data Dictionary Metadata in a Non-CDB"
在CDB中,数据字典元数据被划分为根和PDBs。在下面的图中,employee和departments表驻留在PDB中。这个用户数据的数据字典也驻留在PDB中。因此,PDB中的TAB$表为employees表和departments表各有一行.(这个比较好理解,以前oracle10g里面的最典型的dba_object或者source中各个用户的数据都有,数据字典直接是个杂货铺子,18c里的这个数据字典貌似有点像user_objects的概念了,仅仅自己的,数据字典小了,纯净了)
Figure 2-4 Data Dictionary Architecture in a CDB
Description of "Figure 2-4 Data Dictionary Architecture in a CDB"
前面的图形显示了PDB中的数据字典包含指向根目录中的数据字典的指针。在内部,oracle提供的对象(如数据字典表定义和PL/SQL包)只在根中表示。.这个体系结构实现了两个主要目标:
-
减少重复
例如,与将DBMS_ADVISOR PL/SQL包的源代码存储在每个PDB中不同,CDB只将其存储在CDB$ROOT中,这可以节省磁盘空间.
-
数据库升级的便捷性
如果每个PDB中都存在数据字典表的定义,如果定义要在新版本中更改,那么每个PDB都需要分别升级以捕获更改。只在根目录中存储表定义一次就可以消除这个问题.
Parent topic: Data Dictionary Architecture in a CDB
2.1.3.2 Metadata and Data Links
CDB 使用内部链接机制来分离数据字典信息.
具体来说,Oracle数据库使用以下自动托管指针:
-
Metadata links
Oracle数据库只在CDB根中存储关于dictionary对象的元数据。例如,位于DBA_OBJECTS数据字典视图之下的OBJ$ dictionary表的列定义仅存在于根目录中。如图2-4所示,每个PDB中的OBJ$表使用一种称为元数据链接的内部机制来指向根目录中存储的OBJ$的定义.
元数据链接对应的数据驻留在它的PDB中,而不是根中。例如,如果您在hrpdb中创建表mytable并向其添加行,那么这些行将存储在PDB数据文件中。PDB和根中的数据字典视图包含不同的行。例如,描述mytable的新行存在于hrpdb中的OBJ$表中,而不在CDB根中的OBJ$表中。因此,查询CDB根中的DBA_OBJECTS和hrdpbobjects中的DBA_OBJECTS会得到不同的结果.
-
Data links
Note:
在Oracle数据库12c版本1(12.1.0.2)中,数据链接被称为对象链接。
在某些情况下,Oracle数据库仅在应用程序根中存储对象的数据(不仅仅是元数据)一次。应用程序PDB使用一种称为数据链接的内部机制来引用应用程序根中的对象。创建数据链接的应用程序PDB也存储数据链接描述。数据链接继承它引用的对象的数据类型.
-
Extended data link
扩展数据链接是数据链接和元数据链接的混合。与数据链接类似,扩展数据链接引用应用程序根中的对象。但是,扩展的数据链接也引用了应用程序PDB中的相应对象。与元数据链接类似,应用程序PDB中的对象从应用程序根中的对应对象继承元数据。
在应用程序根中查询时,扩展的数据链接对象仅从应用程序根获取行。然而,当在应用程序PDB中查询时,扩展的数据链接对象从两个appli中获取行.
oracle数据库自动创建和管理到CDB$ROOT的元数据和数据链接。用户不能添加、修改或删除这些链接.
See Also:
-
Oracle Database Concepts for an overview of the data dictionary
Parent topic: Data Dictionary Architecture in a CDB
2.1.3.3 Container Data Objects in a CDB
容器数据对象是包含与多个容器或整个cdb相关的数据的表或视图.
容器数据特权支持一个通用需求,其中多个PDBs驻留在一个CDB中,但是具有不同的本地管理需求。例如,如果应用程序dba不想在本地进行管理,那么他们可以在适当的视图上向普通用户授予容器数据特权。在这种情况下,管理员可以访问这些PDBs的数据。相反,不希望CDB管理员访问其数据的PDB管理员不会授予容器数据特权.
容器数据对象的例子是oracle提供的以V$和CDB_开头的视图。所有容器数据对象都有一个CON_ID列。下表显示了此列值的含义
Table 2-1 Container ID Values
Container ID | Rows pertain to |
---|---|
|
Whole CDB, or non-CDB |
|
|
|
|
All Other IDs |
User-created PDBs, application roots, or application seeds |
在CDB中,对于每个DBA_视图,都存在一个相应的CDB_视图。CDB_视图的所有者就是相应的DBA_视图的所有者。下图显示了不同类别的字典视图之间的关系:
Figure 2-5 Dictionary Views in a CDB(下面这个图太经典了,必须了解)
Description of "Figure 2-5 Dictionary Views in a CDB"
测试:
创建了3,4,5三个pdb,每个pdb中的sys用户下创建test表(orclpdb中的test用户下也创建了个test表),cdb中也创建了sys.test表
在根下查询的层级关系如下图
select 'CDB_',a.CON_ID,(select name from v$containers where con_id=a.CON_ID),a.* from cdb_tables a where TABLE_NAME='TEST';
select 'DBA_',a.* from dba_tables a where TABLE_NAME='TEST';
select 'ALL_',a.* from all_tables a where TABLE_NAME='TEST';
select 'USER_',a.* from user_tables a where TABLE_NAME='TEST';
测试完毕。
当当前容器是PDB时,用户只能查看当前PDB的数据字典信息。对于连接到PDB的应用程序,数据字典与非cdb一样出现。但是,当当前容器是根容器时,普通用户可以查询CDB_视图,以查看根容器的元数据和该用户有权使用的PDBs的元数据。
Note:
当查询从根容器,CDB_和V $隐式转换数据视图AL32UTF8字符集。如果一个字符集需要更多字节来表示一个字符转换为AL32UTF8时,如果视图列宽不能适应特定的PDB数据,那么数据截断是可能的.
下表显示了涉及CDB_视图查询的场景。每行描述在前一行的操作之后发生的操作.
Table 2-2 Querying CDB_ Views
Operation | Description |
---|---|
|
The |
|
|
|
|
|
The |
|
|
这个实验比较好做,看一下就了解了
SQL> select count(*) from cdb_users;
COUNT(*)
----------
147
SQL> select con_id,count(*) from cdb_users group by con_id;
CON_ID COUNT(*)
---------- ----------
1 35
5 38
4 36
3 38
SQL> alter session set container=orclpdb;
Session altered
SQL> select con_id,count(*) from cdb_users group by con_id;
CON_ID COUNT(*)
---------- ----------
3 38
SQL>
See Also:
"About CDB and Container Information in Views" to learn more about container data objects
Parent topic: Data Dictionary Architecture in a CDB
2.1.3.4 Data Dictionary Storage in a CDB
The data dictionary that stores the metadata for the CDB as a whole is stored only in the system tablespaces.
存储特定PDB元数据的数据字典存储在专用于此PDB的自包含表空间中。PDB表空间包含应用程序后端的数据和元数据。因此,每一组数据字典表都存储在自己的专用表空间集中.
See Also:
-
Oracle Database Concepts for an overview of the data dictionary
Parent topic: Data Dictionary Architecture in a CDB
2.1.4 Current Container
对于给定的会话,当前容器是会话运行的容器。当前容器可以是CDB根、应用程序根或PDB。
每个会话在任何时候都只有一个当前容器。由于每个容器中的数据字典是独立的,Oracle数据库使用当前容器中的数据字典进行名称解析和权限授权.
See Also:
Parent topic: Overview of Containers in a CDB
2.1.5 Cross-Container Operations
跨容器操作是一个DDL或DML语句,同时影响多个容器。
只有连接到CDB根或应用程序根的公共用户才能执行跨容器操作。
跨容器操作可能会产生影响:
-
The CDB itself
-
Multiple containers within a CDB
-
Multiple phenomena such as common users or common roles that are represented in multiple containers
-
A container to which the user issuing the DDL or DML statement is currently not connected
跨容器DDL操作的例子包括用户系统通常授予另一个普通用户特权(参见“在CDB中通常授予的角色和特权”),以及ALTER数据库……适用于整个国开行的收回语句.
当您连接到CDB根或应用程序根时,您可以执行单个DML语句来修改容器中多个PDBs中的表或视图。数据库从DML语句中指定的CON_ID列的值推断目标PDBs。如果没有指定CON_ID,则数据库使用ALTER PLUGGABLE数据库容器默认目标语句指定的CONTAINERS_DEFAULT_TARGET属性。
Example 2-3 Updating Multiple PDBs in a Single DML Statement
在本例中,您的目标是将country_name列设置为sh.salestable中的值USA。这个表存在于两个单独的PDBs中,容器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);
In the preceding UPDATE
statement, sal
is an alias for CONTAINERS(sh.sales)
.
这个操作在Application Containers中操作,在普通cdb的pdbs之间没任何影响,仅仅是处理自己的current表,已测试
后面测试Application pdb时,测试一下,目前还没了解清楚
See Also: