Oracle® Multitenant
Administrator’s Guide
Part I Multitenant Architecture
2 Overviewof the Multitenant Architecture
2.1Overview of Containers in a CDB
2.2 Overview of Commonality in the CDB
2.3Overview of Applications in an Application Container
2.4Overview of Services in a CDB
2.5Overview of Tablespaces and Database Files in a CDB
2.6Overview of Availability in a CDB
2.7Overview of Oracle Resource Manager in a CDB
Part I 多租户体系结构概述
本章描述了多租户体系结构中最重要的组件。
2.1 CDB中容器概述
容器是多租户容器数据库(CDB)中的模式、对象和相关结构的集合。在CDB中,每个容器都有惟一的ID和名称。
2.1.1 CDB Root和系统容器
CDB Root(也称为root)是所有pdb所属的模式、模式对象和非模式对象的集合。
每个CDB都有且只有一个名为CDB$root的root容器。root存储管理pdb所需的系统元数据。所有pdb都属于root。系统容器是CDB root以及属于此root的所有pdb。
CDB root不存储用户数据。Oracle建议您不要在root中添加公共对象,也不要在root中修改Oracle提供的架构。但是,您可以为数据库管理创建公共用户和角色。具有必要权限的普通用户可以在容器之间切换。
Oracle建议对root字符集使用AL32UTF8。具有不同字符集的pdb可以驻留在同一CDB中,而不需要进行字符集转换。
示例2-1CDB中的所有容器
以下查询由连接到CDB root的管理用户发出,列出CDB中的所有容器(包括seed和CDB root),按CON_ID排序。
COL NAME FORMAT A15
SELECTNAME, CON_ID, DBID, CON_UID,GUIDFROM V$CONTAINERS ORDERBY CON_ID;
NAME CON_ID DBID CON_UID GUID
------------- ------ ---------- ------------------------------------------
CDB$ROOT 11895287725 12003321 EDD4F60D6E0534E40E40A41C5
PDB$SEED 227953865052795386505200 AC90679F07B55E05396C0E40A23FE
SAAS_SALES_AC 312396464231239646423200 B4CE0A8DC1D24E05396C0E40AF8EE
SALESPDB 436925496343692549634200 B4928319C1BCCE05396C0E40A2432
HRPDB 537844830903784483090200 B4928319D1BCCE05396C0E40A2432
2.1.2 pdb
PDB是一组用户创建的模式、对象和相关结构,它们在逻辑上作为单独的数据库出现在客户机应用程序中。
无论哪个用户创建了PDB,每个PDB都属于SYS。SYS是CDB的一个常见用户。
2.1.2.1 PDBs的种类
除了由oracle提供的PDB$SEED之外,所有的PDB都是用户使用CREATE PLUGGABLE DATABASE语句创建的。
您可以创建以下类型的pdb。
标准PDB
这种类型的PDB是在运行CREATE PLUGGABLE DATABASE时产生的,不需要将PDB指定为种子、代理PDB或应用程序root。它的功能取决于你在其中创建它的容器:
•pdb插入到CDB root
这个PDB属于CDB root容器,而不是应用程序容器。这种类型的PDB不能使用应用程序公共对象。参见“应用程序公共对象”。
•应用PDB
一个应用程序PDB恰好属于一个应用程序容器。与插入到CDB root中的PDBs不同,应用程序PDBs可以在应用程序容器共享主应用程序定义。例如,应用程序root中的usa_zipcodes表可能是一个数据链接的公共对象,这意味着它包含所有插入到这个root的应用程序pdb都可以访问的数据。不驻留在应用程序容器中的pdb不能访问其应用程序公共对象。
应用程序root
将应用程序root看作特定于应用程序的root容器。它充当应用程序后端的主定义(包括通用数据和元数据)的存储库。要创建应用程序root,请连接CDB根,并在create PLUGGABLE DATABASE语句中指定AS application CONTAINER子句。
Seed PDBs
与标准PDB不同,Seed PDB不支持应用程序。相反,seed是创建支持应用程序的pdb的模板。seed可以是下列任何一种:
•seedPDB插入CDB root(PDB$SEED)
您可以使用这个系统提供的模板在应用程序容器或系统容器中创建新的pdb。系统容器只包含一个PDB seed。您不能删除PDB$SEED,或向其中的对象添加对象或修改对象。
•Applicationseed PDB
为了加速在应用程序容器中创建应用程序PDBs,您可以创建一个可选的应用程序seed。应用程序容器包含零个或一个应用程序seed。
您可以通过连接到应用程序容器并执行CREATE PLUGGABLE DATABASE ... AS SEED的声明。
Proxy PDBs
Proxy PDB是一个PDB,它使用一个数据库链接来引用远程CDB中的PDB。当PDB打开时,在Proxy PDB中发出一条语句,该语句将在引用的PDB中执行。
在连接到CDB root或应用程序root时,必须创建一个Proxy PDB。您可以像修改标准PDB一样修改或删除Proxy PDB。
2.1.2.2 PDBs的用途
对于应用程序,PDB是一个自包含的、功能齐全的Oracle数据库。您可以将PDBs合并到单个CDB中,以实现规模经济,同时保持PDBs之间的隔离。
您可以使用PDBs来实现以下具体目标:
•存储特定于应用程序的数据
例如,销售应用程序可以有自己的专用PDB,而人力资源应用程序可以有自己的专用PDB。或者,您可以创建一个应用程序容器,它是一个命名的pdb集合,用于存储一个包含公共数据和元数据的应用程序后端(请参阅“关于应用程序容器”)。
•将数据转移到不同的CDB
数据库是“可插拔的”,因为您可以将其作为一个自包含的单元(称为未插拔的PDB)进行打包,然后将其移动到另一个CDB中。
•执行快速升级
您可以在较低的Oracle数据库版本中将PDB从CDB中拔出来,然后将其插入到较高版本的CDB中。
•快速复制数据而不丢失可用性
对于测试和开发,您可以在PDB保持打开状态时克隆它,将克隆存储在相同或不同的CDB中。您可以选择将PDB指定为可刷新的克隆PDB。或者,您可以使用oracle提供的种子PDB或用户创建的应用程序种子来复制新的PDBs。
•在不同的CDB中引用数据
您可以创建一个代理PDB,它引用一个不同的PDB,或者在同一个CDB中,或者在一个单独的CDB中。当您在代理PDB中发出语句时,它们将在引用的PDB中执行。
•在PDBs中隔离授权
具有适当权限的本地或公共用户可以将架构对象上的执行权限授予单个PDB中的PUBLIC。
2.1.2.3 Proxy PDBs
代理PDB引用远程PDB,称为引用的PDB。
虽然在代理(引用)PDB中发出SQL语句,但是这些语句在引用的PDB中执行。在这方面,代理PDB有点类似于Linux中的符号链接文件。
代理PDBs提供以下好处:
•聚合来自多个应用程序模型的数据
代理PDBs使您能够构建能够聚合来自多个源的数据的位置透明应用程序。这些数据源可以位于同一个数据中心,也可以分布在多个数据中心之间。
•允许一个CDB中的应用程序root将应用程序更改传播到另一个应用程序root
假设CDBs cdb_prod和cdb_test具有相同的应用程序模型。您可以在cdb_prod中的应用程序容器中创建一个代理PDB,它引用cdb_test中的一个应用程序root。当您在cdb_prod的应用程序root中运行安装和升级脚本时,Oracle数据库将这些语句传播到代理PDB,而代理PDB又将它们远程发送到cdb_test中的应用程序root。
通过这种方式,cdb_test中的应用程序root成为cdb_prod中的应用程序root的副本。
要创建代理PDB,请使用AS proxy FROM子句执行create PLUGGABLE DATABASE,其中FROM指定引用的PDB名称和一个数据库链接。创建语句只复制属于SYSTEM和SYSAUX表空间的数据文件。
例2-2创建Proxy PDB
这个示例连接到本地生产CDB中的容器saas_sales_ac。sales_admin普通用户创建了一个名为sales_sync_pdb的代理PDB。这个应用程序PDB在远程开发CDB中引用一个名为saas_sales_test_ac的应用程序root,它使用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;
2.1.2.4 PDB的命名
CDB中的容器共享相同的名称空间,这意味着它们在这个名称空间中必须有唯一的名称。
下列容器的名称不得与同一开发银行的名称冲突:
•CDB root
•插入CDB root的pdbs
•Application roots
•Application PDBs
例如,如果同一个CDB包含应用程序容器saas_sales_ac和saas_sales_test_ac,那么两个都命名为cust1的应用程序pdb不能同时驻留在两个容器中。命名空间规则还防止在CDB根目录中创建名为cust1pdb的PDB,在应用程序根目录中创建名为cust1pdb的PDB。
PDBs和Application roots必须遵循与服务名称相同的命名规则。此外,由于PDB或应用程序根具有具有自己名称的服务,因此容器名称在所有通过特定侦听器公开其服务的CDBs之间必须是惟一的。用户创建的容器名的第一个字符必须是字母数字,其余字符要么是字母数字,要么是下划线(_)。因为服务名是大小写不敏感的,所以容器名是大小写不敏感的,并且是大写的,即使使用带分隔符的标识符指定也是如此。
2.1.2.5 PDBs之间的Database Links
默认情况下,连接到一个PDB的用户必须使用Database Links来访问另一个PDB中的对象。
图2-1PDBs之间的Database Links
在本例中,PDB管理员连接到名为hrpdb1的PDB。默认情况下,在此用户会话期间,c##dba不能在不指定Database Links的情况下查询hrpdb2中的emp2表。
规则的例外情况包括:
•一个数据链接的公共对象,所有包含指向该对象的数据链接的应用程序pdb都可以访问该对象。例如,应用程序容器saas_sales_ac可能在其应用程序中包含数据链接表usa_zipcodes。在这种情况下,普通CDB用户c##dba可以连接到这个容器中的应用程序PDB,然后查询usa_zipcodes,即使实际的表驻留在应用程序根目录中。在这种情况下,不需要数据库链接。
SQL中的CONTAINERS()子句由CDB根或应用程序根发出。使用此子句,可以跨插入到容器根的所有pdb查询数据。
当创建代理PDB时,您必须在CREATE PLUGGABLE database ... AS PROXY子句中指定一个数据库链接名作为代理声明。如果代理PDB和引用的PDB位于单独的CDB中,那么必须在包含代理PDB的CDB的根中定义数据库链接。数据库链接必须连接到远程引用的PDB或远程CDB的CDB ROOT。
2.1.3 CDB中的数据字典体系结构
从用户和应用程序的角度来看,CDB中每个容器中的数据字典是独立的。
例如,每个PDB中的DBA_OBJECTS视图可以显示不同数量的行。这种字典分离使Oracle数据库能够分别从彼此和root管理pdb。
2.1.3.1 CDB数据字典分离的目的
在CDB中,数据字典元数据在CDB root和pdb之间进行拆分。
在新创建的还不包含用户数据的CDB中,CDB root中的数据字典只包含系统元数据。例如,TAB$表包含仅描述Oracle提供的表的行,例如TRIGGER$和SERVICE$。下图描述了三个底层数据字典表,红色的条表示描述系统的行。
假设您创建了一个PDB,然后创建了一个hr模式,其中包含这个PDB中的employees和departments表。PDB中的数据字典包含一些描述oracle提供的实体的行,以及一些描述用户创建实体的行。例如,PDB字典中的TAB$表有雇员表的一行元数据和部门表的一行元数据。
前面的图形显示PDB中的数据字典包含指向CDB根目录中的数据字典的指针。在内部,oracle提供的对象(如数据字典表定义和PL/SQL包)仅在CDB根中表示一次。该架构实现了CDB的两个主要目标:
•减少重复
例如,与在每个PDB中存储DBMS_ADVISOR PL/SQL包的源代码不同,CDB只在CDB$ROOT中存储一次代码,这节省了磁盘空间。
•数据库升级容易
如果数据字典表的定义存在于每个PDB中,并且定义将在一个新版本中更改,那么每个PDB将需要分别升级以捕获更改。只在CDB root中存储一次表定义可以消除这个问题。
2.1.3.2元数据和数据链接
CDB使用内部链接机制来分隔数据字典信息。具体来说,Oracle数据库使用以下自动管理指针:
•元数据链接
Oracle数据库只在CDB根目录中存储关于dictionary对象的元数据。例如,作为DBA_OBJECTS数据字典视图基础的OBJ$ dictionary表的列定义只存在于CDB根目录中。如图2-3所示,每个PDB中的OBJ$表使用一个称为元数据链接的内部机制来指向存储在CDB根目录中的OBJ$的定义。
元数据链接对应的数据位于其PDB中,而不是位于CDB根目录中。例如,如果您在hrpdb中创建表mytable并向其添加行,那么这些行将存储在PDB数据文件中,而不是存储在CDB根数据文件中。
PDB和CDB根中的数据字典视图包含不同的行。例如,描述mytable的新行存在于hrpdb中的OBJ$表中,而不存在于CDB根中的OBJ$表中。因此,对CDB根中的DBA_OBJECTS和hrdpb中的DBA_OBJECTS的查询会显示不同的结果。
•数据链接
在某些情况下,Oracle数据库只在应用程序容器的应用程序根目录中存储一次对象的数据(不仅仅是元数据)。考虑一家电子商务公司,它为不同的地区提供不同的pdb。应用程序根可能存储一个名为postal_codes的表,该表列出了所有美国邮政编码。此容器中的每个应用程序PDB都需要访问公共postal_codes表。
应用程序PDB使用一种称为数据链接的内部机制来引用应用程序根中的对象。创建数据链接的应用程序PDB也存储数据链接描述。数据链接继承它所引用的对象的数据类型。
•扩展数据链接
扩展数据链接是数据链接和元数据链接的混合。与数据链接类似,扩展数据链接引用应用程序根中的对象。但是,扩展的数据链接也引用应用程序PDB中相应的对象。例如,一个应用程序PDB可能有一个扩展的数据链接表,其中存储了美国邮政编码和加拿大邮政编码。与元数据链接类似,应用程序PDB中的对象从应用程序根中的相应对象继承元数据。
在应用程序根中查询时,扩展的数据链接表仅从应用程序根(例如,仅从美国邮政编码)获取行。但是,当在应用程序PDB中查询时,扩展的数据链接表同时从应用程序根和应用程序PDB中获取行,例如,美国邮政编码和加拿大邮政编码。
Oracle数据库自动创建和管理元数据和指向CDB$ROOT的数据链接。用户不能添加、修改或删除这些链接。
2.1.3.3 CDB中的容器数据对象
容器数据对象是一个表或视图,其中包含与多个容器或整个CDB相关的数据。
容器数据特权支持一个通用需求,其中多个pdb驻留在一个CDB中,但是具有不同的本地管理需求。例如,如果应用程序dba不希望本地管理,那么他们可以将适当视图上的容器数据特权授予普通用户。在这种情况下,CDB管理员可以访问这些pdb的数据。相反,不希望CDB管理员访问其数据的PDB管理员不授予容器数据特权。
容器数据对象的例子是oracle提供的视图,其名称以V$和CDB_开头。所有容器数据对象都有一个CON_ID列。下表显示了本列值的含义。
在CDB中,对于每个DBA_view,都存在一个对应的CDB_ view。CDB_ view的所有者是相应的DBA_ view的所有者。下图显示了不同类别的字典视图之间的关系:
当当前容器是PDB时,用户只能查看当前PDB的数据字典信息。但是,当当前容器是CDB root时,普通用户可以查询CDB_视图来查看CDB root的元数据和该用户享有特权的PDBs的元数据。
注:
当从CDB root查询时,CDB_和V$views隐式地将数据转换为AL32UTF8字符集。如果字符集在转换为AL32UTF8时需要更多字节来表示字符,并且如果视图列宽不能容纳来自特定PDB的数据,则可以进行数据截断。
下表描述了CDB_views的查询。每一行描述在前一行中的操作之后发生的操作。
表2-2查询CDB_views
操作:
SQL>CONNECTSYSTEM
Enterpassword:********
Connected.
描述:
system用户(对于CDB中的所有容器都是通用的)连接到CDB root(参见“CDB中的通用用户”)。
操作:
SQL>SELECTCOUNT(*)FROM CDB_USERS WHERE CON_ID=1;
COUNT(*)
--------
38
描述:
SYSTEM查询CDB_USERS以获得CDB ROOT中的公共用户数量。输出表明CDB ROOT中有38个通用用户。
操作:
SQL>SELECTCOUNT(DISTINCT(CON_ID))FROM CDB_USERS;
COUNT(DISTINCT(CON_ID))
-----------------------
4
描述:
SYSTEM查询CDB_USERS来确定CDB中不同容器的数量。
操作:
SQL>CONNECTSYSTEM@hrdb
Enterpassword:********
Connected.
描述:
SYSTEM用户现在连接到名为hrpdb的PDB。
操作:
SQL>SELECTCOUNT(*)FROM CDB_USERS;
COUNT(*)
----------
48
描述:
SYSTEM查询CDB_USERS。输出表明当前容器hrpdb中存在48个通用和本地用户。
操作:
SQL>SELECTCOUNT(*)FROM DBA_USERS;
COUNT(*)
----------
48
描述:
SYSTEM查询DBA_USERS。输出与前一个查询相同。因为系统没有连接到CDB ROOT,所以DBA_USERS视图显示了与CDB_USERS相同的输出。因为DBA_USERS只显示当前容器中的用户,所以它显示48。
2.1.3.4数据字典存储在CDB中
存储整个CDB元数据的数据字典只存储在system表空间中。
存储特定PDB元数据的数据字典存储在专用于该PDB的自包含表空间中。PDB表空间包含应用程序后端的数据和元数据。因此,每组数据字典表都存储在自己的一组专用表空间中。
2.1.4当前容器
对于给定的会话,当前容器是会话正在其中运行的容器。当前容器可以是CDB root、应用程序root或PDB。
每个会话在任何时候都只有一个当前容器。因为每个容器中的数据字典是独立的,所以Oracle数据库使用当前容器中的数据字典进行名称解析和特权授权。
2.1.5 cross-container操作
cross-containe操作是同时影响多个容器的DDL或DML语句。
只有连接到CDB root或应用程序root的普通用户才能执行跨容器操作。cross-container操作可影响:
•CDB本身
•CDB中的多个容器
•多个现象,如在多个容器中表示的通用用户或通用角色
•发出DDL或DML语句的用户当前未连接到的容器
跨容器DDL操作的示例包括用户系统通常授予另一个普通用户特权(请参阅“在CDB中通常授予的角色和特权”),以及ALTER数据库……适用于整个CDB的恢复语句。
当您连接到CDB根或应用程序根时,您可以执行单个DML语句来修改容器中多个pdb中的表或视图。数据库根据DML语句中指定的CON_ID列的值推断目标PDBs。如果没有指定CON_ID,那么数据库使用ALTER PLUGGABLE database CONTAINERS DEFAULT TARGET语句指定的CONTAINERS_DEFAULT_TARGET属性。
例2-3在一个DML语句中更新多个pdb
在本例中,您的目标是将country_name列设置为sh.sales表中的USA值。此表存在于两个独立的pdb中,容器id分别为7和8。两个pdb都位于名为saas_sales_ac的应用程序容器中。您可以作为管理员连接到应用程序root,并进行如下更新:
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是容器的别名(sh.sales)。
更多数据库相关学习资料,可以查看我的ITPUB博客,网名chenoracle:
http://blog.itpub.net/29785807/