Oracle 12c多租户架构下的应用容器

应用场景:
CDB中包含多个PDB,如果这些PDB中运行着同样的应用,可以将应用作为服务来提供给多个客户,在这种场景下,可以为每个客户准备一个PDB,然后每一个PDB都包含其自有数据,但是数据模型相同,并将其链接到该应用的跟容器上。

(1)实验版本
SQL> select banner from v$version where rownum=1;
BANNER
--------------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

(2)首先我们创建应用的跟容器,它其实还是一个PDB,只是使用了as application container字句:
SQL> show parameter inst
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
_datafile_write_errors_crash_instance boolean     FALSE
active_instance_count                integer
cluster_database_instances           integer     1
instance_abort_delay_time            integer     0
instance_groups                      string
instance_mode                        string      READ-WRITE
instance_name                        string      orcl
instance_number                      integer     0
instance_type                        string      RDBMS
instant_restore                      boolean     FALSE
open_links_per_instance              integer     4
parallel_instance_group              string

SQL> show pdbs
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 ORCLPDB1                       MOUNTED
         4 ORCLPDB2                       MOUNTED
         5 ORCLPDB3                       MOUNTED

SQL> create pluggable database lkapp_root as application container admin user lkapp_admin identified by oracle roles=(DBA);
Pluggable database created.

SQL> alter pluggable database lkapp_root open;
Pluggable database altered.

SQL> show pdbs
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 ORCLPDB1                       MOUNTED
         4 ORCLPDB2                       MOUNTED
         5 ORCLPDB3                       MOUNTED
         6 LKAPP_ROOT                     READ WRITE NO
         
(3)然后即可以连接到该PDB,并声明我们要开始应用的安装:
配置tnsnames.ora:
lkapp_root =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 12cr2)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = lkapp_root)
    )
  )
  
SQL> conn sys/oracle@lkapp_root as sysdba或者alter session set container=lkapp_root;
SQL> alter pluggable database application lkapp begin install '1.0';
Pluggable database altered.

(4)现在我们就可以创建所需要的表空间和用户了:
SQL> create tablespace lkapp_data datafile size 10m autoextend on next 10m maxsize unlimited;
Tablespace created.
SQL> create user lkapp_owner identified by oracle default tablespace lkapp_data container=all;
User created.
SQL> grant create session,create table to lkapp_owner;
Grant succeeded.
SQL> alter user lkapp_owner quota unlimited on lkapp_data;
User altered.

(5)现在我们已经有了应用的所有者,我们可以创建应用方案。
在本例中,我们将会创建一个公共元数据表(对于每一个应用租户来说,结构都是相同的,但数据不同)以及一张公共数据表(对于所有租户来说都是相同的),语法如下:
SQL> alter session set current_schema=lkapp_owner;
Session altered.
SQL> create table lkapp_table sharing=metadata (id number primary key);
Table created.
SQL> create table lkapp_static sharing=data (id number primary key,name varchar2(20));
Table created.
SQL> insert into lkapp_static values (1,'aaa');
1 row created.
SQL> insert into lkapp_static values (2,'bbb');
1 row created.
SQL> commit;
Commit complete.

(6)一旦这些任务完成,我们就可以声明应用安装结束:
SQL> alter pluggable database application lkapp end install '1.0';
Pluggable database altered.

(7)在这个例子中,就可以看到,我们已经设置了应用的名称及版本号。当然,这只是应用于初始安装,但是在应用的整个声明周期中打补丁与升级管理时,所使用的语法也是类似的。
现在我们可以为每一个应用租户创建一个PDB。为完成这一点,我们需要连接到应用跟容器:
conn sys/oracle@lkapp_root as sysdba或者alter session set container=lkapp_root;
SQL> create pluggable database lkapp_one admin user lkapp_one_admin identified by oracle;
Pluggable database created.
SQL> alter pluggable database lkapp_one open;
Pluggable database altered.
此时,pdb lkapp_one就属于应用跟容器了,但它是空的。通过进行同步操作,就可以将其连接到应用跟容器的元数据和数据,如下:
conn sys/oracle@lkapp_one as sysdba或者alter session set container=lkapp_one;
SQL> alter session set container=lkapp_one;
Session altered.
SQL> alter pluggable database application lkapp sync;
Pluggable database altered.

(8)此时,所有的事情都已经准备就绪,我们的用户和表也都在应用容器lkapp_one了,如下:
conn lkapp_owner/oracle@lkapp_one或者alter session set container=lkapp_one;
SQL> alter session set container=lkapp_one;
Session altered.
SQL> show pdbs
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         7 LKAPP_ONE                      READ WRITE NO
SQL> alter pluggable database application lkapp sync;
Pluggable database altered.
SQL> alter session set current_schema=lkapp_owner;
Session altered.
SQL> desc lkapp_table
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                        NOT NULL NUMBER
SQL> select * from lkapp_static;
        ID NAME
---------- ----------
         1 aaa
         2 bbb

(9)创建应用容器pdb lkapp_two进行演示
SQL>  create pluggable database lkapp_two admin user lkapp_one_admin identified by oracle;
Pluggable database created.
SQL> alter pluggable database lkapp_two open;
Pluggable database altered.
SQL> alter session set container=lkapp_two;
Session altered.
SQL> alter pluggable database application lkapp sync;
Pluggable database altered.
SQL> alter session set container=lkapp_two;
Session altered.
SQL> show pdbs
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         8 LKAPP_TWO                      READ WRITE NO
SQL> alter pluggable database application lkapp sync;
Pluggable database altered.
SQL> alter session set current_schema=lkapp_owner;
Session altered.
SQL>  desc lkapp_table
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                        NOT NULL NUMBER
SQL> select * from lkapp_static;
        ID NAME
---------- ----------
         1 aaa
         2 bbb
SQL> show pdbs
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         8 LKAPP_TWO                      READ WRITE NO

(10)最后,回到CDB$ROOT,并检查这些容器的信息:
SQL> conn / as sysdba
Connected.
SQL> col name format a10
SQL> col application_root format a5
SQL> col application_pdb format a5
SQL> select con_id,name,application_root,application_pdb,application_root_con_id from v$containers;
    CON_ID NAME       APPLI APPLI APPLICATION_ROOT_CON_ID
---------- ---------- ----- ----- -----------------------
         1 CDB$ROOT   NO    NO
         2 PDB$SEED   NO    NO
         3 ORCLPDB1   NO    NO
         4 ORCLPDB2   NO    NO
         5 ORCLPDB3   NO    NO
         6 LKAPP_ROOT YES   NO
         7 LKAPP_ONE  NO    YES                         6   <--LKAPP_ONE的跟容器是LKAPP_ROOT
         8 LKAPP_TWO  NO    YES                         6   <--LKAPP_TWO的跟容器是LKAPP_ROOT
8 rows selected.


版权声明:本文为lk_db原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。