
3.7 CDB用户、PDB用户及角色管理
多租户架构中的用户管理和Non-CDB数据库中的用户管理有所区别,新增了两个概念,即公共用户(Common User)和本地用户(Local User),与之对应的角色是公共角色(Common Role)和本地角色(Local Role)。
3.7.1 用户
公共用户可以在CDB和PDB中同时存在,能够连接root和PDB并进行操作;而本地用户只在特定的PDB中存在,也只能在特定的PDB中进行操作。在PDB中不能创建公共用户,在CDB中(CDB$ROOT中)不能创建本地用户。
1.公共用户
在CDB中创建公共用户需要以C##开头(由参数COMMON_USER_PREFIX控制),而在Non-CDB中用户名不能以C##开头,用户名不区分大小写。
错误语法:

正确语法:

当公共用户创建成功后,默认情况下会在CDB中的所有PDB中创建公共用户,代码如下:

注意,以C##开头是由参数COMMON_USER_PREFIX控制的,如果该参数值为空,则没有该要求,但是Oracle不建议这么做。

2.本地用户
本地用户和Non-CDB中的用户没有区别。只能在PDB中创建本地用户,无法在CDB root中创建本地用户。本地用户无法登录其他PDB或root,在不同的PDB中本地用户的用户名可以相同。和公共用户名的名称必须以C##开头不同,创建本地用户时名称不能以C##开头。
错误语法:


正确语法:

3.7.2 角色
角色是一些权限的集合。一个角色里包含了各种权限,主要是为了管理方便,不用一个一个地赋予或撤回。从Oracle 12c开始,用户创建的角色要么是公共角色,要么是本地角色。和用户一样,公共角色对所有PDB都有效,而本地角色只对指定的PDB(创建角色所在的PDB)有效,并且公共角色的名称也必须以C##开头,受参数COMMON_USER_PREFIX的控制。
只要用户和角色在容器中同时存在,就可以正常地将角色赋给相应的用户,而不管是公共用户还是本地用户。其他PDB中的本地角色不能在另一个PDB中使用,因为该角色只存在于指定的PDB中。
1.公共角色
公共角色存在于CDB root或应用程序root中,对其中所有的PDB都有效。公共角色分为Oracle自带和用户自定义两种。
(1)Oracle自带:例如DBA、PUBLIC等角色。
(2)用户自定义:用户通过CREATE ROLE … CONTAINER=ALL语句在CDB root或应用程序root中创建的角色。角色的名称必须唯一且以C##开头。相关操作如下。
确认当前容器是root,代码如下:

名称不以C##开头来创建角色,会报如下错误:


正常创建角色并给角色赋权限,代码如下:

将公共角色赋给公共用户,代码如下:

查看角色是否是公共角色,代码如下:

创建一个和已存在的角色名称相同的角色,代码如下:

2.本地角色
本地角色仅存在于单个PDB中,即创建该角色的PDB中,其他PDB无法使用该角色。本地角色的名称在不同的PDB中可以是一样的,也就是说,两个PDB中的本地角色的名称可以是相同的。实际上从数据库的角度也很好理解,多租户的概念主要就是为了区分PDB,各个PDB之间是完全独立的。
创建本地角色并赋权限,其语法如下:


查看角色属性,代码如下:
