Oracle数据库12c多租户架构概念篇二

本文详细介绍了Oracle CDB中的容器管理机制,包括数据字典架构、容器数据对象、跨容器操作等内容,并深入探讨了CDB中的用户、角色及权限管理方式。


续前节 http://blog.itpub.net/26696047/viewspace-2131917/


1. CDB中的容器(补充)

1CDB中的数据字典架构

在一个CDB内部,各容器的数据字典是相互独立的。这样可以分开管理,互不影响。

先来看非CDB的情况,当数据库刚创建时,还没有用户数据写入,此时数据字典中仅包含系统元数据。如下图:

当用户创建了一些schematable之后,数据字典便加入了它们的信息。如下图:

对于CDB而言,情况略有不同,如下图:

可以看出,此时数据字典被分成了两部分,CDB中系统的元数据(数据库初始创建时的元数据)存储在root容器中,而各个PDB中仅存储用户数据的元数据。此外,Oracle内部提供的一些对象,例如数据字典表定义和PL/SQL包仅存在于root容器中。

在上边的结构中,root容器就像一个中枢,或者根节点。数据字典中的元数据虽然做了分离,但肯定不能完全断绝开,否则信息就不完整了。于是,PDB中的数据字典包含一个指针指向root容器中的数据字典。

这种结构有什么好处呢?有以下两点:

1)减少复制。例如,对于一些PL/SQL源代码,可以只在root容器中存储一份,以节省磁盘空间。

2)方便数据库升级。升级可能会带来数据字典定义的改变,以上结构避免了对每个PDB进行升级。

2CDB Root中的元数据和对象链接

前边提到了PDB中数据字典到root中数据字典的指针,特别地,Oracle数据库使用以下自动管理的指针:

1)元数据链接

关于数据字典对象的元数据,仅存在于root中。例如,字典表OBJ$的列定义(用于DBA_OBJECTS视图),只存在于root中。那么,PDB中的OBJ$表就使用元数据链接指向root中的OBJ$定义。

与一个元数据链接对应的数据驻留在它的PDB中,而不是root。举个例子,你在PDB hrpdb中创建了一个表mytable,一行新的描述mytable表的数据将存在于hrpdb中的OBJ$表中,但不在rootOBJ$表中。这样,当你查询dba_objects视图时,会发现在hrpdbroot中将显示不同的结果集。

2)对象链接

有一些对象数据(非元数据),Oracle仅在root中存储一次。例如,AWR数据存储在root中。每个PDB使用一种叫做对象链接的内部机制来指向root中的AWR数据,这样在每个单独的容器中就可以访问诸如DBA_HIST_ACTIVE_SESS_HISTORY DBA_HIST_BASELINE这样的视图。

元数据链接和对象链接由Oracle数据库自动创建和管理,用户不能添加、修改和移除这些链接。

3CDB中的容器数据对象

前边我们提到在CDB中,由于数据字典的隔离结构,我们在不同的容器中查询同样的数据字典视图(我们在非CDB中经常用到的),会得到不同的结果集。对于诸如表空间数据文件也是一样,例如当你连接到root容器查询dba_tablespaces视图时,会发现只有几个默认提供的表空间。

而容器数据对象仿佛打破了这种限制,让你可以在CDB层面有更大的可见范围。一个容器数据对象是一个表或者视图,包含有属于多个容器也有可能属于整个CDB的数据,同时包括将对特定通用用户可见的这些对象限定在一个或多个容器的机制。

容器数据对象的例子是Oracle提供的一些以V$CDB_开头的一些视图。所有的容器数据对象有一列CON_ID,意为容器的ID号,不同ID号的指代关系如下:

在一个CDB中,对于每个DBA_视图,有一个对应的CDB_视图存在。CDB_视图的所有者是对应DBA_视图的所有者。如下图:

显然,CDB_视图的可见范围更大。但是通过CDB_视图查看整个CDB范围的数据字典信息,你必须连接到root容器。同时,连接的用户得是通用用户和特权用户。

4)当前容器与跨容器操作

对于一个给定的session,当前容器就是该会话所运行在的容器。当前容器可以是root(仅对于通用用户)或者一个PDB

在任意时刻,每个会话仅有一个当前容器。因为每个容器的数据字典是独立的,Oracle数据库使用当前容器中的数据字典进行名称解析和权限认证。

一个跨容器操作是一个DDL语句,将影响以下任意项:

     - CDB本身

     - 多个容器

     - 多个通用用户或者角色

     - 与正在执行DDL语句的用户所连接到的容器不同的容器

只有连接到root的通用用户可以执行跨容器操作。例子包括SYSTEM用户将权限赋给另一个通用用户,和一个应用于整个CDBALTER DATABASE…RECOVER语句。   

4. CDB中的用户和角色

通过前面的讨论,我们可以发现CDB是一个统一的整体,而在这个统一体内部,每个PDB又是相互独立的个体。统一与独立仿佛是矛盾的,但又完美地结合,满足我们不同维度的需求。CDB中用户和角色的设计让这种体系更加生动。

1CDB中的通用用户和本地用户

CDB中的用户分成了两类,即Common UserLocal User,姑且翻译为通用用户和本地用户。顾名思义,前者是整个CDB层面,面向所有容器的,而后者则局限于某个特定的PDB。如下图:

1)通用用户

通用用户在所有容器中有着相同的身份。有以下特点:

  通用用户可以连接到任意容器(包括ROOT),只要有在其中CREATE SESSION权限。

一个通用用户不必在所有的容器中拥有相同的权限。

  用户创建的通用用户的名字必须以c##或者C##开头。

  通用用户的名字必须只包含ASCII EBCDIC字符。

  每个通用用户在所有容器之间是唯一命名的。

  一个通用用户的schema在每个容器中可以是不同的

例如,假设c##dba是一个通用用户,且在多个容器中拥有权限,那么c##dba schema在这些容器的每一个当中可能包含不同的对象。

2)本地用户

本地用户只能在一个PDB内有效,但是,不同的PDB却可能有相同名称的本地用户。

  一个本地用户属于一个特定的PDB,并且在这个PDB中拥有一个schema

本地用户不能创建在root容器中。

  一个PDB中的一个本地用户不能登录到其他PDB或着ROOT

如果想访问其他PDB,可以通过database link

  本地用户的名字不能以c## or C##开头。

  一个本地用户的名字仅在其PDB内须是唯一的。

  一个本地用户是否可以访问一个common schema中的对象,取决于它们的用户权限。 

2CDB中的通用角色和本地角色

oracle内部的权限管理中,角色是很重要的。用户和角色都可以作为被赋权的对象,因而可以对比着理解。Oracle内置的角色都是common的,用户可以自行创建通用角色或者本地角色。

1)通用角色

通用角色存在于所有容器中,可以很方便地支持一些跨容器的操作。用户可以自行创建通用角色,用户创建的通用角色名字必须以C##或c##开头,并且必须只包含ASCII or EBCDIC字符。 

2)本地角色

一个本地角色只存在于单个的PDB中,并且它所包含的角色和权限,只能应用于它所在的容器。

同样地,同一个CDB中的PDB可能有同名的本地角色。但它们其实是互不相干的。 

3)赋权概览

有了用户、角色、权限,就可以进行赋权操作了。而这就是复杂之处了,因为赋权这个操作也分commonlocal

首先我们有一个预备前提,就是在一个CDB中,每一个赋权动作,不管是本地的还是common的,都发生在一个特定容器中。这很好理解,因为一个会话在任意时刻都要有一个当前容器。

然后我们有两条原则:

- Both common and local phenomena may grant and be granted locally.

- Only common phenomena may grant or be granted commonly.

也就是说对于common的赋权动作,限制会多一些。

那么,common的赋权和local的赋权动作效果有何不同呢,下图大概说明了这一点:

简单地将,如果是common grant,会影响到所有的容器;如果是local grant,那么只会影响赋权发生的容器。

这里先再补充一点,讲到赋权,往往涉及到三个要素,即赋权者(grantor),被赋权者(grantee),以及所赋的角色或权限(role or privilege)。赋权这个动作,就是grantorrole或者privilege赋给grantee的过程。而grantor只能是usergrantee可以是user,也可以是role。另外,userrole都是有common/local属性的,而privilege则不作此讨论。

明确了上述几点,我们后边就可以通过表格分别阐述两种grant了。

1)本地赋权

前边提到,本地赋权对于三要素(common or local)的限制少一些。除了前边提到的三要素,我们还有三种“Phenomenon”,即userroleprivilege,加上userrolecommon/local属性,共有5类。下表从这一角度来阐述赋权操作:

Phenomenon

可以本地地赋权

可以被本地地赋给

可以收到本地赋予的角色或权限

通用用户

Yes

N/A

Yes

本地用户

Yes

N/A

Yes

通用角色

N/A

Yes1

Yes

本地角色

N/A

Yes2

Yes

权限

N/A

Yes

N/A

1.角色中的权限只对赋权发生的容器中的grantee是可用的,无论权限被赋给角色时是commonly还是locally

2.角色中的权限只对角色被赋予和被创建所在的容器中的grantee是可用的

上表乍一看挺复杂,但是明确了前边提到的三要素,5Phenomenon,就很好理解了。如上表第二列,就是Phenomenon作为grantor来讲的,第三列就是作为role/privilege,第四列就是作为grantee。可以看到,除了N/A(没有意义)的,其他都是Yes,也就是说对于赋权动作没啥限制。但是,通过两条脚注可以看到,对赋权生效范围是有限制的。

本地赋权要满足一下条件:

  赋权者要有必需的权限。

对于系统角色或权限,grantor要有其ADMIN OPTION;对于对象角色或权限,grantor要有其GRANT OPTION

  赋权只在一个容器生效

默认地,GRANT语句包含CONTAINER=CURRENT从句。

2)一般(common)赋权

对应于本地赋权,还可以commonly赋权。这个限制比较多,要求三要素都是common的(除了privilege不作讨论)。类似地,我们有下表:

Phenomenon

可以common地赋权

可以被common地赋给

可以收到common赋予的角色或权限

通用用户

Yes

N/A

Yes

本地用户

No

N/A

No

通用角色

N/A

Yes1

Yes

本地角色

N/A

No

No

权限

N/A

Yes

N/A

1.被一般地赋给一个通用角色的权限对所有容器的grantee是可用的。另外,如果通用角色中的某些权限是被本地赋予的,那么这些权限只对它们被赋给通用角色所在的容器内的grantee是可用的。

如脚注所述,在common赋权场景下,由于通用角色也可能包含本地赋予的权限,所以你在将它们赋给别人时,在不同容器产生的效果就会有差别。这些本地赋予的权限还是会局限在当时的PDB

Common赋权需要具备的条件:

  Grantor是一个通用用户

  Grantee是一个通用用户或角色

  Grantor有赋权所需的必要权限

对于系统角色或权限,grantor要有其ADMIN OPTION;对于对象角色或权限,grantor要有其GRANT OPTION

  赋权应用于所有容器

GRANT语句包含CONTAINER=ALL从句。

  如果一个角色被赋予了,那它一定是common的;如果一个对象权限被赋予了,那么相应的对象是common的。 

4)赋权给CDB中的PUBLIC

在一个CDB中,PUBLIC是一个通用角色。在一个PDB中,本地赋予PUBLIC的权限使所有本地和通用用户能够限于在该PDB中执行此权限。

注意:

赋予Oracle提供的用户和角色的每个权限和角色是被一般地赋予的,除了赋给PUBLIC的系统权限,是本地的。这一例外存在的原因是你有可能想收回一些赋权,而这些是Oracle默认包含的。

Oracle建议不要common地赋予PUBLIC角色和权限。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26696047/viewspace-2132406/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26696047/viewspace-2132406/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值