eygle.com   eygle.com
eygle.com eygle
eygle.com  
 

« Oracle 12c 多租户:PDB 支持 abort 关闭么? | Blog首页 | Oracle 12c:多租户数据库克隆 ORA-01276 错误处理一例 »

Oracle 12c多租户新特性:Common用户和Local用户的管理
modb.pro

编辑手记:这一节我们将介绍多租户架构中用户及权限的变化,全局用户和本地用户,管理方式和内部实现,这篇文章来自<深入解析Oracle>一书的摘录。云和恩墨 的很多客户已经采用多租户特性进行生产部署,这一技术早已经走入实践

无论在CDB和Non-CDB数据库中,用户都拥有一个Schema,拥有一系列的Schema对象,在CDB中由于PDB的引入,用户范畴有所不同。

在CDB模式下,公用用户(Common User)和本地用户(Local User)两个概念被引入进来,公用用户可以在CDB和PDB中同时存在,能够连接ROOT和PDB进行操作;而本地用户则只在特定的PDB中存在,也只能在特定的PDB中执行操作;在PDB中不能创建公用用户,而在CDB中(CDB$ROOT中)同样不能创建本地用户。


在CDB中创建的公用用户要求以c##或C## 开头,以下测试以常规方式命名的用户将会创建失败,符合规则的用户可以被创建:

SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production

SQL> create user eygle identified by eygle;
create user eygle identified by eygle
            *
第 1 行出现错误:
ORA-65096: 公用用户名或角色名无效

SQL> create user c##eygle identified by eygle;

用户已创建。

当创建公用用户时,Oracle会向每个PDB中同时创建该用户,如果PDB未打开,则创建工作会以任务的方式延后。

以下查询显示数据库中只在容器1中存在新创建的用户:

SQL> select username,common,con_id from cdb_users where username like '%EYGLE%';

USERNAME                       COM     CON_ID
------------------------------ --- ----------
C##EYGLE                       YES          1

此时打开PDB,则数据库会自动完成之前挂起的内部创建工作:

SQL> alter pluggable database enmo open;

插接式数据库已变更。

SQL> select username,common,con_id from cdb_users where username like '%EYGLE%';

USERNAME                       COM     CON_ID
------------------------------ --- ----------
C##EYGLE                       YES          1
C##EYGLE                       YES          3


SQL> drop user c##eygle;

用户已删除。

下图描述了公用用户和本地用户的区别:

cdbpdb.png

在拥有了CREATE SESSION权限后,公用用户能够登陆包括Root在内的任何Container。公用用户一般在每个PDB中都存在对应的用户信息,在PDB中不能存在与公用用户重名的用户,如初始的SYS和SYSTEM用户都属于公用用户。也只有公用用户能够授权或被授权相应的公用角色和权限。
公用权限是指对所有Container都有效的系统或者对象权限,例如一个公用用户被授予了公用权限 CREATE ANY TABLE WITH ADMIN OPTION 可以将这个权限转授给其他公用用户.公用用户之外的权限被称为本地权限(Local Privilege).
公用角色是指在所有Container中都可见的角色,这些角色可能包含全局和本地权限。本地角色只能包含本地权限。授予公用角色的公用权限,对于具有该角色的用户在任何可以连接的Container中都将具有该权限。
以下是一些相关的常识性介绍:

  • 一个公用用户在不同Container中的Schema可以不同;
  • 本地用户只能在各自的PDB中进行操作,在不同PDB中可以存在同名的本地用户;
  • PDB中的本地用户不能登陆其他PDB或ROOT;
  • PDB的本地用户只需要在本PDB内保持用户名唯一;
  • 本地用户能否访问一个公用Schema中的对象取决于其拥有的具体权限;
  • PDB能够通过DB Link访问其他的PDB;

在CDB、PDB模式下,一个权限在被授权的Container中存在。因此,在PDB中授予的本地权限和角色和在Non-CDB中没有不同,例如,在PDB HRPDB中授予本地用户HR的 SELECT ANY TABLE权限,仅在该PDB中生效。
相对而言,公用权限和角色可以跨越Container生效,当需要跨Container进行操作时,需要公用权限或角色,并且这些权限需要在现有和将来创建的Container中生效。
在CDB中,每个权限或者是在某个Container中的本地权限,或者是在所有Container中生效的公用权限。公用权限确保公用用户无需在不同PDB中重复授权。
类似CREATE ANY TABLE的权限,其自身既不是公用权限也不是本地权限,如果一个用户通过CONTAINER=CURRENT方式授权,则被授权用户拥有的是本地权限;如果一个权限通过CONTAINER=ALL方式授权,则用户获得的是公用权限。因此,一个权限称其为本地或公用权限,完全依赖于其授权方式。

在CDB中,每个角色或者是基于PDB的本地角色,或者是对全体PDB生效的公用角色,所有系统提供的角色(如DBA)都属于公用角色。

在视图DBA_USERS和CDB_USERS中都包含了一个字段COMMON,用于标识公用用户和本地用户。

SQL> select username,common from dba_users;

USERNAME		       COM
------------------------------ ---
AUDSYS			       YES
SYSKM			       YES
XS$NULL 		       YES
XDB			       YES
WMSYS			       YES
DBSNMP			       YES
SYSDG			       YES
SYSBACKUP		       YES
SYS			       YES
SYSTEM			       YES

以下查询显示SYSTEM作为公用用户在四个容器中存在:

SQL> select username,common,con_id from cdb_users where username='SYSTEM';

USERNAME		       COM     CON_ID
------------------------------ --- ----------
SYSTEM			       YES	    1
SYSTEM			       YES	    2
SYSTEM			       YES	    3
SYSTEM			       YES	    4

数据库中存在17个公用用户:

SQL> select count(distinct username) from cdb_users where common='YES';

COUNT(DISTINCTUSERNAME)
-----------------------
		     17

以下查询列出了数据库中的本地用户:

SQL> select username,con_id from cdb_users where common='NO';

USERNAME			   CON_ID
------------------------------ ----------
ENMO					3
EYGLE					3
JULIA					3
ENMO					4
EYGLE					4
JULIA					4

通过指定CONTAINER可以限定创建用户的类型,当使用ALL选项时,以下命令就创建了一个名为APPADMIN的公用用户:

SQL> create user c##admin identified by appadmin container=ALL;

User created.

SQL> select username,common,con_id from cdb_users where username='C##ADMIN';

USERNAME		       COM     CON_ID
------------------------------ --- ----------
C##ADMIN		       YES	    1
C##ADMIN		       YES	    3
C##ADMIN		       YES	    4

查询dba_users视图,可以看到APPADMIN的相关用户属性:

SQL> select username,common from dba_users where username='C##ADMIN';

USERNAME		       COM
------------------------------ ---
C##ADMIN		       YES

注意,在CDB$ROOT中不能创建本地用户或角色:

SQL> create user appdba identified by appdba container=CURRENT;
create user appdba identified by appdba container=CURRENT
                                 *
第 1 行出现错误:
RA-65049: 不允许在 CDB$ROOT 中创建本地用户或角色

在PDB中才可以创建本地用户,以下测试首先连接到PDB(名称为ENMO)中,连接用户具备DBA权限可以创建用户:

SQL> connect eygle/eygle@enmo
Connected.
SQL> show con_id con_name

CON_ID
------------------------------
3

CON_NAME
------------------------------
ENMO

当然在PDB中也不允许创建公用用户:

SQL> create user appdba identified by appdba container=ALL;
create user appdba identified by appdba container=ALL
                                 *
第 1 行出现错误:
ORA-65050: 只允许在 CDB$ROOT 中执行公用 DDL
同样在PDB中也不能删除公用用户:
SQL> drop user c##eygle;
drop user c##eygle
*
第 1 行出现错误:
ORA-65050: 只允许在 CDB$ROOT 中执行公用 DDL
以下SQL成功在PDB下创建了本地用户:
SQL> create user appdba identified by appdba container=CURRENT;

User created.


SQL> select username,common,con_id from cdb_users where username='APPDBA';

USERNAME		       COM     CON_ID
------------------------------ --- ----------
APPDBA			       NO	    3
类似的,本地用户不能被授予公用权限或角色,以下尝试在全局授权的命令会返回明确的错误:
SQL> select username,common from dba_users where username='APPDBA';

USERNAME		       COM
------------------------------ ---
APPDBA			       NO

SQL> grant create session to appdba container=ALL;
grant create session to appdba container=ALL
*
第 1 行出现错误:
ORA-65030: 用户无法向本地用户或角色授予公用权限
在PDB内授予本地权限之后,新创建的用户可以登陆本地PDB数据库:
SQL> grant create session to appdba ;

Grant succeeded.

SQL> connect appdba/appdba@enmo
Connected.
SQL> show con_id con_name

CON_ID
------------------------------
3

CON_NAME
------------------------------
ENMO
下面来研究一下角色。在CDB_ROLES视图可以查询CDB的角色信息,以下查询可以看到由于PDB的引入,角色记录大大增加:
SQL> select count(distinct role),count(*) from cdb_roles;

COUNT(DISTINCTROLE)   COUNT(*)
------------------- ----------
		 44	   174
对于DBA公用角色来说,在每个Container中都存在相应的信息记录:
SQL> select role,common,con_id from cdb_roles where role='DBA';

ROLE			       COM     CON_ID
------------------------------ --- ----------
DBA			       YES	    1
DBA			       YES	    2
DBA			       YES	    3
DBA			       YES	    4
而对于PDB_DBA角色,仅在PDB中存在:
SQL> select role,common,con_id from cdb_roles where role='PDB_DBA';

ROLE			       COM     CON_ID
------------------------------ --- ----------
PDB_DBA 		       NO	    3
PDB_DBA 		       NO	    4
SQL> select con_id,name from v$pdbs;

    CON_ID NAME
---------- ------------------------------
	 2 PDB$SEED
	 3 ENMO
	 4 YUNH
同用户管理类似,在CDB$ROOT中可以建立公用角色,但是不能创建本地角色,公用角色在每个PDB中都存在,同样需要以c##为前缀开头:
SQL> show con_id con_name

CON_ID
------------------------------
1

CON_NAME
------------------------------
CDB$ROOT
SQL> create role APPROLE container=ALL;
create role APPROLE container=ALL
            *
第 1 行出现错误:
ORA-65096: 公用用户名或角色名无效

SQL> create role C##ROLE container=ALL;

角色已创建。

SQL> select role,common,con_id from cdb_roles where role='C##ROLE';

ROLE			       COM     CON_ID
------------------------------ --- ----------
C##ROLE 		       YES	    1
C##ROLE 		       YES	    3
C##ROLE 		       YES	    4

SQL> create role APPADMIN container=CURRENT;
create role APPADMIN container=CURRENT
*
第 1 行出现错误:
ORA-65049: 不允许在 CDB$ROOT 中创建本地用户或角色
在PDB中,同样不能创建公用角色,仅能创建本地角色:
SQL> connect sys/oracle@enmo as sysdba
Connected.
SQL> select count(role) from dba_roles;

COUNT(ROLE)
-----------
	 45

SQL> create role COMMON_ROLE container=ALL;
create role COMMON_ROLE container=ALL
*
ERROR at line 1:
ORA-65050: Common DDLs only allowed in CDB$ROOT


SQL> create role APPENMO container=CURRENT;

Role created.

SQL> select role,common from dba_roles where role='APPENMO';

ROLE			       COM
------------------------------ ---
APPENMO 		       NO

SQL> select count(role) from dba_roles;

COUNT(ROLE)
-----------
	 46
对于系统权限和对象权限,CDB相应的增加了对应视图用于存储这些信息:
SQL> connect / as sysdba
Connected.
SQL> desc system_privilege_map
 Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 PRIVILEGE				   NOT NULL NUMBER
 NAME					   NOT NULL VARCHAR2(40)
 PROPERTY				   NOT NULL NUMBER

SQL> desc table_privilege_map
 Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 PRIVILEGE				   NOT NULL NUMBER
 NAME					   NOT NULL VARCHAR2(40)

SQL> desc cdb_sys_privs
 Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 GRANTEE					    VARCHAR2(128)
 PRIVILEGE					    VARCHAR2(40)
 ADMIN_OPTION					    VARCHAR2(3)
 COMMON 					    VARCHAR2(3)
 CON_ID 					    NUMBER

SQL> desc cdb_tab_privs
 Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 GRANTEE					    VARCHAR2(128)
 OWNER						    VARCHAR2(128)
 TABLE_NAME					    VARCHAR2(128)
 GRANTOR					    VARCHAR2(128)
 PRIVILEGE					    VARCHAR2(40)
 GRANTABLE					    VARCHAR2(3)
 HIERARCHY					    VARCHAR2(3)
 COMMON 					    VARCHAR2(3)
 TYPE						    VARCHAR2(24)
 CON_ID 					    NUMBER
在CDB中可以像在NON-CDB的数据库中一样进行权限授予与回收:
SQL> connect sys/oracle@enmo as sysdba
Connected.
SQL> select grantee,privilege,common,con_id from cdb_sys_privs where grantee='APPDBA';

GRANTEE 	     PRIVILEGE				      COM     CON_ID
-------------------- ---------------------------------------- --- ----------
APPDBA		     CREATE SESSION			      NO	   3

SQL> grant create table to appdba;

Grant succeeded.

SQL> select grantee,privilege,common,con_id from cdb_sys_privs where grantee='APPDBA';     

GRANTEE 	     PRIVILEGE				      COM     CON_ID
-------------------- ---------------------------------------- --- ----------
APPDBA		     CREATE TABLE			      NO	   3
APPDBA		     CREATE SESSION			      NO	   3
SQL> revoke create table from appdba;

Revoke succeeded.

SQL> select grantee,privilege,common,con_id from cdb_sys_privs where grantee='APPDBA';   

GRANTEE 	     PRIVILEGE				      COM     CON_ID
-------------------- ---------------------------------------- --- ----------
APPDBA		     CREATE SESSION			      NO	   3

欢迎加入『云和恩墨大讲堂』,参与我们的学习和讨论。
YhemTalk.jpeg

历史上的今天...
    >> 2011-12-02文章:
    >> 2007-12-02文章:
    >> 2006-12-02文章:
           落后的技术就是灾难
    >> 2005-12-02文章:
           Today is the Birthday Of AnAn

By eygle on 2016-12-02 18:23 | Comments (0) | Oracle12c/11g | 3219 |


CopyRight © 2004~2020 云和恩墨,成就未来!, All rights reserved.
数据恢复·紧急救援·性能优化 云和恩墨 24x7 热线电话:400-600-8755 业务咨询:010-59007017-7040 or 7037 业务合作: marketing@enmotech.com