CDB组件(Components of a CDB)
一个CDB数据库容器包含了下面一些组件:
ROOT组件
ROOT又叫CDB$ROOT, 存储着ORACLE提供的元数据和Common User,元数据的一个例子是ORACLE提供的PL/SQL包的源代码,Common User 是指在每个容器中都存在的用户。
SEED组件
Seed又叫PDB$SEED,这个是你创建PDBS数据库的模板,你不能在Seed中添加或修改一个对象。一个CDB中有且只能有一个Seed. 这个感念,个人感觉非常类似SQL SERVER中的model数据库。
PDBS
CDB中可以有一个或多个PDBS,PDBS向后兼容,可以像以前在数据库中那样操作PDBS,这里指大多数常规操作。
这些组件中的每一个都可以被称为一个容器。因此,ROOT(根)是一个容器,Seed(种子)是一个容器,每个PDB是一个容器。每个容器在CDB中都有一个独一无二的的ID和名称。
select con_id,dbid,NAME,OPEN_MODE from v$pdbs;
CBD:
alter PLUGGABLE database pdb1 open;
alter PLUGGABLE database pdb1 close;
PDB:
alter PLUGGABLE database all open;
alter PLUGGABLE database all close;
alter session set container=pdb1;
--自动启动PDB
--在12.1.0.2及其以后版本,可以通过设置
ALTER PLUGGABLE DATABASE PDB SAVE STATE;
--来实现在cdb open之后业务pdb能够自动open.
sqlplus sys/xifenfei@pdb1 as sysdba ##连接CDB
show con_name;
[oracle@xifenfei ~]$ sqlplus / as sysdba
SQL> alter session set container=pdb1; ##切换到PDB
show con_name;
创建用户: 在cdb中只能创建全局用户(c##开头)
create user c##xff identified by xifenfei;
SELECT USERNAME,CON_ID,USER_ID FROM CDB_USERS WHERE USERNAME;
SQL> alter session set container=pdb1;
SQL> show con_name
CON_NAME
------------------------------
PDB1
SQL> create user xff identified by xifenfei;
创建用户默认的是container=all,在cdb中只能创建全局用户(c##开头),会在cdb和所有的pdb中创建该用户(但是pdb中的全局用户需要另外授权才能够在pdb中访问)。在pdb中只能创建的用户为本地用户
用户授权
SQL> grant connect to c##xff;
Grant succeeded.
SQL> select GRANTEE,con_id from cdb_ROLE_PRIVS where GRANTED_ROLE='CONNECT' AND GRANTEE='C##XFF';
SQL> grant resource to c##xff container=all;
Grant succeeded.
SQL>select GRANTEE,con_id from cdb_ROLE_PRIVS where GRANTED_ROLE='RESOURCE' AND? GRANTEE='C##XFF';
用户授权默认情况下是只会给当前container,在cdb中也可以指定container=all,对所有open的pdb且存在该用户都进行授权
修改参数:
1.cDB
alter system set open_cursors=500 container=all;
2.pdb
SQL> conn sys/xifenfei@pdb1 as sysdba
SQL> alter database open;
SQL> alter system set open_cursors=100;
这里可以看到在cdb中修改,pdb会继承进去;如果在pdb中修改会覆盖pdb从cdb中继承的参数含义
在ORACLE 12C中参数文件只是记录了cdb的参数信息,没有记录任何的pdb的信息,那ORACLE是如何管理使得各个pdb有自己的参数,这里通过试验的出来ORACLE 12C CDB环境中是通过参数文件结合
PDB_SPFILE$来实现参数管理
pdb信息
select PDB_NAME,CON_UID,pdb_id,status from dba_pdbs;
select con_id,dbid,NAME,OPEN_MODE from v$pdbs;
CDB$ROOT中修改参数
--指定container=all
SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT
SQL> alter system set open_cursors=500 container=all;
SQL> show parameter open_cursors;
SQL> alter session set container=pdb1;
SQL> show con_name
SQL> show parameter open_cursors;
--在CDB$ROOT中修改不指定container参数,表示全部pdb生效
SQL> alter session set container=CDB$ROOT;
SQL> alter system set open_cursors=100;
SQL>? show parameter open_cursors;
SQL> alter session set container=pdb1;
SQL> show parameter open_cursors;
--指定container=current
SQL> alter system set open_cursors=120 container=current;
SQL> show parameter open_cursors;
SQL> alter session set container=pdb2 ;
SQL> show parameter open_cursors;
这里可以看出来,在ROOT中修改参数,默认情况和指定container=all/current均是所有open的pdb都生效.
这里有个疑问ORACLE的参数文件只是记录的cdb的sid的参数,并未记录各个pdb的参数,那是如何实现cdb中各个pdb参数不一致的呢?继续分析
修改pdb参数做10046
SQL> show con_name;
CON_NAME
------------------------------
PDB1
SQL> oradebug setmypid
oradebug event 10046 trace name context forever ,level 12;
SQL> oradebug TRACEFILE_NAME /u01/app/oracle/diag/rdbms/cdb/cdb/trace/cdb_ora_18377.trc
SQL> alter system set sessions=100;
SQL> oradebug event 10046 trace name context off;
--继续修改pdb参数
SQL> alter session set container=pdb1;
SQL>oradebug setmypid
SQL> oradebug EVENT 10046 TRACE NAME CONTEXT FOREVER, LEVEL 12
SQL>oradebug TRACEFILE_NAME /u01/app/oracle/diag/rdbms/cdb/cdb/trace/cdb_ora_20275.trc;
SQL> alter system set sessions=101;
SQL> oradebug EVENT 10046 trace name context off;
分析trace文件
--第一次修改pdb参数值
insert into pdb_spfile$(db_uniq_name, pdb_uid, sid, name, value$, comment$) values(:1,:2,:3,:4,:5,:6);
--第二次修改pdb参数值(相同参数)
update pdb_spfile$ set value$=:5, comment$=:6 where name=:1 and pdb_uid=:2 and db_uniq_name=:3 and sid=:4;
这里我们发现在独立修改pdb参数之时,其本质是在pdb_spfile$基表中插入或者修改相关记录(第一次修改插入,后续修改是更新)
关于pdb_spfile$基表分析
select con_id,owner,object_type from cdb_objects where object_name='PDB';
SELECT DB_UNIQ_NAME,PDB_UID,NAME,VALUE$ FROM PDB_SPFILE$;
ALTER SESSION SET CONTAINER=pdb1;
SQL>SELECT DB_UNIQ_NAME,PDB_UID,NAME,VALUE$ FROM PDB_SPFILE$;
证明pdb中不同于root的参数是记录在root的PDB_SPFILE$基表中.
整个CDB的工作原理是如果在PDB_SPFILE$中无相关参数记录,则继承cdb的参数文件中值,
如果PDB_SPFILE$中有记录则使用该值覆盖cdb参数文件值.
删除PDB_SPFILE$验证
select value$ from pdb_spfile$ where name='open_cursors';
delete from pdb_spfile$ where name='open_cursors';
删除PDB_SPFILE$中相关记录,pdb的参数值会自动继续继承cdb中参数值
cdb中参数关系,在cdb中修改,会默认所有pdb均自动继承;如果在pdb中修改值会覆盖cdb参数,而且只对当前pdb生效,并记录在 PDB_SPFILE$
在ORACLE 12C中引入了CDB和PDB的概念,实现了ORACLE数据库的可插拔,在一个CDB数据库中,有多个PDB,而每一个PDB又可以理解为一个独立的传统ORACLE 数据库,
那为了能够通过一个sql查询获得整个CDB数据库的信息,ORALCE 引入了 CDB_* 开头的视图,该视图就是在传统的 DBA_* 视图基础之上增加了CON_ID,用来区分不同的PDB,
从而实现了一个简单sql查询在有足够权限的情况下,可以查询所有PDB中信息
确定是否是CDB
SELECT CDB FROM V$DATABASE;
CDB中各容器信息
SELECT NAME, CON_ID, DBID, CON_UID, GUID FROM V$CONTAINERS ORDER BY CON_ID;
elect CON_NAME_TO_ID('PDB1') FROM DUAL;
SELECT CON_DBID_TO_ID(3313918585) FROM DUAL;
SELECT CON_UID_TO_ID(3313918585) FROM DUAL;
PDB部分信息
SELECT PDB_ID, PDB_NAME, STATUS FROM DBA_PDBS ORDER BY PDB_ID;
SELECT NAME, OPEN_MODE, RESTRICTED, OPEN_TIME FROM V$PDBS;
CDB中查询对象信息
SELECT p.PDB_ID, p.PDB_NAME, t.OWNER, t.TABLE_NAME
FROM DBA_PDBS p, CDB_TABLES t
WHERE p.PDB_ID > 2
AND T.TABLE_NAME='COL$'
AND p.PDB_ID = t.CON_ID
ORDER BY p.PDB_ID;
查询在CDB中的PDB数据/临时文件信息
SELECT p.PDB_ID, p.PDB_NAME, d.FILE_ID, d.TABLESPACE_NAME, d.FILE_NAME
FROM DBA_PDBS p, CDB_DATA_FILES d
WHERE p.PDB_ID = d.CON_ID
ORDER BY p.PDB_ID;
SELECT CON_ID, FILE_ID, TABLESPACE_NAME, FILE_NAME
FROM CDB_TEMP_FILES
ORDER BY CON_ID;
查询PDB的service信息
SELECT PDB, NETWORK_NAME, CON_ID FROM CDB_SERVICES
WHERE PDB IS NOT NULL AND
CON_ID > 2
ORDER BY PDB;
PDB中可以修改参数
SELECT NAME FROM V$SYSTEM_PARAMETER
WHERE ISPDB_MODIFIABLE = 'TRUE'
ORDER BY NAME;
查看PDB历史信息
SELECT DB_NAME, CON_ID, PDB_NAME, OPERATION, OP_TIMESTAMP, CLONED_FROM_PDB_NAME
FROM CDB_PDB_HISTORY
WHERE CON_ID > 2
ORDER BY CON_ID;
CREATE PDB
SELECT NAME,CDB FROM V$DATABASE;
select pdb_id,pdb_name,dbid,STATUS,CREATION_SCN from dba_pdbs;
CREATE PLUGGABLE DATABASE xff_db ADMIN USER xff IDENTIFIED BY xifenfei
STORAGE (MAXSIZE 2G MAX_SHARED_TEMP_SIZE 100M)
DEFAULT TABLESPACE xifenfei
DATAFILE '/u01/app/oracle/oradata/xifenfei/xff/xifenfei01.dbf' SIZE 25M AUTOEXTEND ON
PATH_PREFIX = '/u01/app/oracle/oradata/xifenfei/xff/'
FILE_NAME_CONVERT = ('/u01/app/oracle/oradata/xifenfei/pdbseed/', '/u01/app/oracle/oradata/xifenfei/xff/');
select pdb_id,pdb_name,dbid,STATUS,CREATION_SCN from dba_pdbs;
OPEN PDB
alter pluggable database xff_db open;
select pdb_id,pdb_name,dbid,STATUS,CREATION_SCN? from dba_pdbs;
alter pluggable database all close immediate;
select con_id,dbid,NAME,OPEN_MODE from v$pdbs;
alter pluggable database all open;
select con_id,dbid,NAME,OPEN_MODE from v$pdbs;
Unplugging a PDB from a CDB
alter pluggable database FF close immediate;
alter pluggable database ff UNPLUG into '/tmp/ff.xml';
DROP PDB
DROP PLUGGABLE DATABASE xff_db INCLUDING DATAFILES;
Plug Unplugged PDB into CDB
create pluggable database ff using '/tmp/ff.xml'
copy file_name_convert=('/u01/app/oracle/oradata/xifenfei/FF/','/u01/app/oracle/oradata/xff_l/xff');
exec DBMS_PDB.SYNC_PDB();
select con_id,dbid,NAME,OPEN_MODE from v$pdbs;
alter pluggable database all open;
ALTER PLUGGABLE DATABASE PDB SAVE STATE来实现在cdb open之后业务pdb能够自动open.
select con_name, state from dba_pdb_saved_states;
在数据库mount状态下save state
ALTER PLUGGABLE DATABASE PDB save state;
pdb为mount状态下,执行save state无记录,证明save state不成功
在数据库open状态下save state—-设置pdb随cdb启动
ALTER PLUGGABLE DATABASE PDB open;
插接式数据库已变更。
ALTER PLUGGABLE DATABASE PDB save state;
插接式数据库已变更。
select con_name, state from dba_pdb_saved_states;
pdb为open状态下,执save state成功.
需要注意 save state 需要在 pdb open情 况下执行才能够生效.
禁用pdb随cdb启动—DISCARD STATE
ALTER PLUGGABLE DATABASE PDB DISCARD state;
12.1.0.1中设置pdb随cdb启动
CREATE TRIGGER open_all_pdbs
AFTER STARTUP
ON DATABASE
BEGIN
EXECUTE IMMEDIATE 'alter pluggable database all open';
END open_all_pdbs;
/
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




