ORACLE 12C Mulititenant的Object Link
在12C中引入了多租户架构,数据字典对像分为了四个层次,USER_,ALL_,DBA_,CDB_. 基中CDB_级别是
查询整个CDB级别的所有容器中的对像.由于CDB级别的对像并不是真正的存放在cdb$root这个容器中,而
是通过查询所有的pdb中数据汇总而来,所以这样的也使得pdb可以plug和unplug到另一个容器中,在12c中
这种方式称为object link.
现在假设数据库中存在两个pdb容器
DONGDONGTANG> select con_id,name,open_mode from v$pdbs;
CON_ID NAME OPEN_MODE
---------- ------------------------------ ----------
2 PDB$SEED READ ONLY
3 PDB1 READ WRITE
4 PDB2 READ WRITE
当前容器名为cdb$root
DONGDONGTANG> show con_name;
CON_NAME
------------------------------
CDB$ROOT
查询CDB级别所有的对像
DONGDONGTANG> select count(*) from cdb_objects;
通过对cdb_objects对像的定义,可以看到oracle使用了一个函数CONTAINERS()来查询所有的PDB中对像,以sys.dba_objects的栏位为准,同时该函
数会在结果集中加入了con_id列
SELECT "OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","LAST_DDL_TIME","TIMESTAMP",
"STATUS","TEMPORARY","GENERATED","SECONDARY","NAMESPACE","EDITION_NAME","SHARING","EDITIONABLE","ORACLE_MAINTAINED","CON_ID"
FROM CONTAINERS("SYS"."DBA_OBJECTS");
手动在cdb$root级别创建一个表
DONGDONGTANG> create table t1 (a int);
Table created.
试图使用系统自带的container的方式访问
DONGDONGTANG> select * FROM CONTAINERS("SYS"."T1");
select *
*
ERROR at line 1:
ORA-12801: error signaled in parallel query server P007
ORA-00942: table or view does not exist
由于这个表在pdb中不存在,所以报错.同时我们也可以根据提示信息看出在pdb中查询使用的是并行查询的方式.所以有大量的pdb的时候需要小心查询
CDB_级别的对像.
接下来我们在两个pdb中分别创建了表T1,然后再次查询
DONGDONGTANG> alter session set container=pdb1;
Session altered.
DONGDONGTANG> create table t1 (a int);
Table created.
DONGDONGTANG> alter session set container=pdb2;
Session altered.
DONGDONGTANG> create table t1 (a int);
Table created.
DONGDONGTANG> alter session set container=cdb$root;
Session altered.
再次在cdb$root中使用CONTAINERS,由于现在每个容器中都有表T1,现在可以返回结果了
DONGDONGTANG> select * FROM CONTAINERS("SYS"."T1");
no rows selected
如果在某个pdb中表的定义不一样呢
DONGDONGTANG> alter session set container=pdb1;
Session altered.
DONGDONGTANG> drop table t1;
Table dropped.
DONGDONGTANG> create table t1 (b int,d int);
Table created
DONGDONGTANG> select * FROM CONTAINERS("SYS"."T1");
select *
*
ERROR at line 1:
ORA-12801: error signaled in parallel query server P006
ORA-00904: "A": invalid identifier
oracle在这个pdb中执行的时候,使用的是类似于select a from t1,由于该栏位不存在,所以报错了.
如果cdb中定义的栏位在pdb中相关的表中都有的,那么查询就不会报错
DONGDONGTANG> create table t1 (a int,d int);
Table created.
查询可以正确的返回.
DONGDONGTANG> select * FROM CONTAINERS("SYS"."T1");
no rows selected
现在我们在cdb$root中的t1 insert数据
DONGDONGTANG> alter session set container=cdb$root;
Session altered.
DONGDONGTANG> insert into t1 values(10);
1 row created.
DONGDONGTANG> commit;
Commit complete.
DONGDONGTANG> select * FROM CONTAINERS("SYS"."T1");
A CON_ID
---------- ----------
10 1
可以看到CONTAINERS函数对查询该记录,并且在结果中增加了一个CON_ID,表示该结果来自哪个CON_ID了.
通过container函数,我们可以看到object link的工作方式,是通过解析相关的对像栏位,再使用并行的方式
在每个pdb中执行,然后再汇总结果返回给用户,这样就实现在CDB级别查看所有数据的功能.通过对该函数我们
可以在用户级别实现同时在多个pdb中查询汇总数据的功能.