增强 Application Container 灵活性
Oracle Application Container 的概念。
简单来说,在有了多租户的体系结构之后,很多 PDB 都可能共用同一套应用架构和元数据,所以 Oracle 在数据库中引入了应用容器的概念,
在应用容器中,首先存在一个 Application Root,可以在其中创建应用 SEED 数据库,种子数据库定义数据结构元数据等信息,然后其他和应用相关的数据库可以由此克隆而来,
加快部署,想一想这样的例子,如果在云上为100家客户部署收费系统,通过这样的Clone就很便捷。
在 Oracle 12.2 中增加的 Container Map 新特性,可以看做一个基于多租户 PDB 的 Sharding 架构,其基本原理是,如果我们在应用容器中构建一个分区表,
其分区可以映射到不同的PDB 中,而在整个应用容器中,数据结构逻辑上是一个整体,各 PDB 仅能操作自己分区的数据,而应用在全局则可以看到所有的数据。
在应用容器全局查询,可以透明的访问数据,而针对特定分区的数据访问会被自动路由到特定的 PDB 执行:
测试过程:
首先创建一个应用容器,这个 PDB 的名称是:apppdb1
create pluggable database apppdb1 as application container admin user apppdb1 identified by apppdb1 file_name_convert=('/opt/oracle/oradata/ORCLCDB','/opt/oracle/oradata/ORCLAPP1');
接下来创建两个区域数据库,分别是 apppdb2 和 apppdb3:
create pluggable database apppdb2 admin user apppdb2 identified by apppdb2 file_name_convert=('/opt/oracle/oradata/ORCLCDB','/opt/oracle/oradata/ORCLAPP2');
create pluggable database apppdb3 admin user apppdb3 identified by apppdb3 file_name_convert=('/opt/oracle/oradata/ORCLCDB','/opt/oracle/oradata/ORCLAPP3');
接下来查看一下这几个数据库的角色,在 Application Root之下,是两个 Application PDB:
alter session set container=apppdb1;
SQL> alter session set container=APPPDB1;
Session altered.
SQL> create pluggable database apppdb2 admin user apppdb2 identified by apppdb2 file_name_convert=('/opt/oracle/oradata/ORCLCDB','/opt/oracle/oradata/ORCLAPP2');
Pluggable database created.
SQL> create pluggable database apppdb3 admin user apppdb3 identified by apppdb3 file_name_convert=('/opt/oracle/oradata/ORCLCDB','/opt/oracle/oradata/ORCLAPP3');
Pluggable database created.
SQL> select con_id,name,open_mode,application_root,application_pdb from v$pdbs;
CON_ID NAME OPEN_MODE APPLIC APPLIC
---------- ------------------------------ -------------------- ------ ------
4 APPPDB1 READ WRITE YES NO
6 APPPDB2 MOUNTED NO YES
7 APPPDB3 MOUNTED NO YES
SQL> alter pluggable database all open;
Pluggable database altered.
SQL> select con_id,name,open_mode,application_root,application_pdb from v$pdbs;
CON_ID NAME OPEN_MODE APPLIC APPLIC
---------- ------------------------------ -------------------- ------ ------
4 APPPDB1 READ WRITE YES NO
6 APPPDB2 READ WRITE NO YES
7 APPPDB3 READ WRITE NO YES
现在对应用容器进行初始化,在其中部署初始的元数据,创建 containermap ,然后创建数据表并对数据表启用 container_map ,最后完成这个应用元数据库的部署:
SQL> alter pluggable database application apppdb1 begin install '1.0';
SQL> create user siyang identified by siyang888;
User created.
SQL> grant dba to siyang;
SQL> create table siyang.containermap (CITY varchar2(20) not null)
2 partition by list (city) (
3 partition apppdb2 values('BEIJING'),
4 partition apppdb3 values('CHENGDU'));
Table created.
SQL> ALTER PLUGGABLE DATABASE SET CONTAINER_MAP='siyang.containermap';
Pluggable database altered.
SQL> create table siyang.emp sharing=metadata (
2 empno number,
3 ename varchar2(20),
4 city varchar2(20));
Table created.
SQL> alter table siyang.emp enable container_map;
Table altered.
SQL> alter table siyang.emp enable containers_default;
Table altered.
SQL> alter pluggable database application apppdb1 end install '1.0';
Pluggable database altered.
在应用PDB中,需要先刷新同步元数据,否则对象信息并不可见:
SQL> alter session set container=apppdb2;
Session altered.
SQL> alter pluggable database application apppdb1 sync;
Pluggable database altered.
SQL> desc siyang.emp;
Name Null? Type
----------------------------------------- -------- ----------------------------
EMPNO NUMBER
ENAME VARCHAR2(20)
CITY VARCHAR2(20)
SQL> insert into siyang.emp values(1,'SIYANG','BEIJING');
1 row created.
SQL> insert into siyang.emp values(1,'WK','BEIJING');
1 row created.
SQL> COMMIT;
Commit complete.
SQL> alter session set container=apppdb3;
Session altered.
SQL> desc siyang.emp
ERROR:
ORA-04043: object siyang.emp does not exist
SQL> alter pluggable database application apppdb1 sync;
Pluggable database altered.
SQL> desc siyang.emp
Name Null? Type
----------------------------------------- -------- ----------------------------
EMPNO NUMBER
ENAME VARCHAR2(20)
CITY VARCHAR2(20)
SQL> insert into siyang.emp values(3,'WANGLEI','CHENGDU');
1 row created.
SQL> COMMIT;
Commit complete.
SQL> select * from siyang.emp;
EMPNO ENAME
---------- ----------------------------------------
CITY
----------------------------------------
3 WANGLEI
CHENGDU
SQL> alter session set container=apppdb2;
Session altered.
SQL> select * from siyang.emp;
EMPNO ENAME
---------- ----------------------------------------
CITY
----------------------------------------
1 SIYANG
BEIJING
1 WK
BEIJING
SQL> alter session set container=apppdb1;
Session altered.
SQL> select * from siyang.emp;
EMPNO ENAME
---------- ----------------------------------------
CITY CON_ID
---------------------------------------- ----------
1 SIYANG
BEIJING 6
1 WK
BEIJING 6
3 WANGLEI
CHENGDU 7
在容器数据库中分别插入数据,注意,在 apppdb2 的数据库中只能插入相关分区的数据,如果试图插入不存在的分区或其他MAP区域数据,会显示出错
注意我接下来切换到另外一个 PDB ,结果发现前面未提交的数据会对后续的操作形成阻塞,事实上这说明 alter session set container 这个 DDL 没有隐式提交之前的事务,必须切换回到原PDB下提交事务
在不同PDB只能查询和操作各自PDB的信息,而在Application Root 则可以查询全部数据
在 18c 增加的动态容器映射特性,允许我们增加、分拆分区数据,进一步的增强了灵活性。
create pluggable database s_asmer container_map update (add partition s_asmer values('XX','XX'));
create pluggable database s_asmer_peru container_map update(split partition s_asmer into (partition s_asmer ('XX'),partion s_asmer_pery));