1.通过名称和ID来识别容器
一个集成的CDB中,可以包含多个容器,他们可以通过名称和数字,也就是con_id来进行识别.在12c版本中,所有用来显示一个实例中包含哪些对象的v$视图,都添加了一列,用来显示CON_ID,以便标记对象属于哪个PDB.
CDB本身是一个容器,其容器CON_ID为0,被标记为CON_ID=0的对象,都是 CDB级别的对象,并且不会关联到其它的容器.
在任意CDB环境中,第一个容器都是根容器,名为CDB$ROOT,并且CON_ID=1,其它所有的容器都是PDB
在任意CDB中的第一个PDB容器,都是种子容器,名为PDB$SEED,因为他的CDB中的第二个容器,所以CON_ID=2
在CON_ID>2的容器就是用户PDB
在PDB中查询dba_pdbs中,CON_UID和DBID一致,表示当前PDB的唯一ID
而在V$DATABASE中查询的DBID是CDB$ROOT的唯一ID,和以前的概念一致.
2.容器列表
视图DBA_PDBS列出了所有的PDB及其状态:
PDB_ID PDB_NAME STATUS DBID CON_ID
---------- ------------------------------ ---------- ---------- ----------
2 PDB$SEED NORMAL 3575060827 2
对于PDB而言,当刚创建时,其状态为NEW,并且在第一次将其以读/写方式打开时,其状态调整为NORMAL,因为在第一次打开PDB的时候,需要进行一些相关操作.状态为UNUSABLE表明该PDB创建失败,并且唯一允许的操作是将其删除.
状态为UNPLUGGED,表明该PDB将会被传输到其它的CDB,而在源CDB上,唯一能做的操作就是将该PDB删除.
SQL> l
1* select con_id,name,open_mode,open_time from v$pdbs
SQL> /
CON_ID NAME OPEN_MODE OPEN_TIME
---------- ------------------------------ ---------- ---------------------------------------------------------------------------
2 PDB$SEED READ ONLY 21-JUN-19 10.31.47.849 AM +08:00
在非PDB中,MOUNTED状态表明当前的控制文件已经被读取,但是数据文件还没有被实例打开.可以使用show pdbs来查看当前的PDB状态,如果正处于根容器中,还可以显示所有的PDB:
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3.通过CON_ID和DBID来识别容器
CON_ID来标识容器,但是当PDB移动的时候,CON_ID就会变化,因此使用CON_UID来唯一标识PDB.
4.连接到容器
使用show con_id和show con_name来查看当前连接的pdb
SQL> show con_id
CON_ID
------------------------------
1
SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT
可以使用alter session命令来切换容器,例如:
SQL> alter session set container=brent;
Session altered.
PDB的隔离性:
在pdb中只能访问到当前PDB的数据.不同PDB之间的操作是相互独立的.你可以使用alter session set container=XX;来在PDB之间进行切换.
但是注意当在一个PDB上进行事务的时候,如果没有提交或者回滚,在不能在另一个PDB上开启事务.
如果你想使用PDB,CDB的特性,则需要使用12c的客户端,否则在执行切换PDB的时候会产生错误.
注意:
不同的PDB可以使用自己的system,sysaux,undo,temp,users表空间(推荐这么做),但是使用共有的redo日志,控制文件和参数文件.
如果想在切换不同的pdb的时候执行不同的参数,可以在PDB中创建BEFORE SET CONTAINER或者AFTER SET CONTAINER触发器.
5.容器中的字典
当你处在PDB中时候,pdb中包含了所有你想从数据库中看到的内容.当你在一个PDB中进行数据字典查询的时候,与你在其它非CDB环境中的一样.DBA_和V$视图都是当前PDB下的.
当你处在CDB的时候,就可以看CDB_视图,这些视图是所有容器DBA_视图的union all结果.这是一个CDB管理员使用的方法,从而查看所有对象.
对于CDB$ROOT用户,v$视图将会显示所有的容器内的信息.例如v$session中con_id标识了此会话当前属于哪个PDB.
6.参数文件
对于所有的容器,spfile是公用的,spfile持有的该实例的相关参数,并为整个CDB进行属性设置.
有些参数可以在PDB级别进行单独配置.具体哪些参数,可以参考v$parameter中的ISPDB_MODIFIABLE为TRUE的列.
如果手工指定了某pdb的参数,那么此pdb的参数将覆盖cdb的参数.不再参考cdb的参数值.而且此pdb的参数是存放在CDB的数据字典PDB_SPFILE$中.
可以通过查看数据字典pdb_spfile$来查看pdb指定的参数:
SQL> select a.name,a.dbid,b.pdb_uid,b.name,b.value$ from v$pdbs a ,pdb_spfile$ b where a.dbid=b.pdb_uid and a.name='PDB2'
SQL> /
NAME DBID PDB_UID NAME VALUE$
------------------------------ ---------- ---------- -------------------------------------------------------------------------------- ------------------------------
PDB2 2158045800 2158045800 db_securefile 'PREFERRED'
PDB2 2158045800 2158045800 open_cursors 1000
注意一个DB_FILES参数,默认为200,当你有很多PDB的时候,可能很快就会超过,因此注意在创建CDB的时候就修改其大小.
7.控制文件
控制文件也是CDB级别的.控制文件是唯一真正存储数据文件名称的地方.例如你在CDB中查询dba_data_files只显示当前CDB的数据文件,并不会列出所有的数据文件,
但是你查询v$datafile会列出所有的数据文件,因为v$datafile查询的是控制文件.
当一个PDB被拔出或者插入的时候,所有与该PDB相关的数据文件信息,也会被控制文件中导出,然后存储到一个XML文件中.
8.UNDO文件
在12.1中UNDO是CDB级别的.
但是在12.2中UNDO可以是PDB级别的,当LOCAL_UNDO被设置为on的时候,每个PDB都拥有自身的UNDO表空间
建议将UNDO本地管理,即每个PDB都拥有其独立的undo,这样可以做到PDB隔离,而且在PDB闪回的时候也更方便.
9.临时表空间
临时表空间可以是PDB或者CDB级别创建,建议每个PDB拥有其独立的临时表空间
如果某个会话在执行的过程中没有指定临时表空间,而且该PDB也没有默认的临时表空间,则使用CDB的临时表空间.
10.redo日志
redo日志是CDB级别的,所有的PDB公用相同的redo日志
CDB环境下的redo日志与以前的类似,但是需要在每一条redo中记录额外的信息用来标记来至哪个容器.
使用统一的redo线程来处理所有的PDB,因此对于DBA管理CDB而言就变得轻松.所有的备份,rac配置,dg配置都是在CDB级别进行配置,PDB会随着CDB自动进行备份,配置,DG等.