2025年10月29日 星期三

7. Application Container

Application Container 是在 Multitenant 中的一種特殊的架構,在既有的 CDB 下建立一個 PDB 作為 Application Root,可以說是在 CDB Root 底下再產生一個 Root ,然後 Application Root底下再建立 Application PDB :

A diagram of a computer application

AI-generated content may be incorrect.

 

建立 Application Root 的用意在於 Application Root 可以與底下的 Application PDB 共享物件,在進行程式部屬或者是更版只需要在 Application Root 進行變更,之後將異動 sync 到底下的 PDB 就好,優點就是同樣的變更無需要每個 PDB 都重複做一次 :

A diagram of a computer application

AI-generated content may be incorrect. 


在建立 PDB 的語法當中加上 as application container 就可以將 PDB建立成為 Application Root :

SQL> create pluggable database pdb_root as application container admin user pdbadmin identified by welcome1 file_name_convert=('pdbseed','pdb_root');

SQL> alter pluggable database pdb_root open;


在 PDB Root 底下建立的 PDB 即為 Application PDB :

SQL> alter session set container=pdb_root;

SQL> create pluggable database pdb_app1 admin user pdbadmin identified by welcome1 file_name_convert=('pdbseed','pdb_app1');

SQL> alter pluggable database pdb_app1 open;


於 CDB 層級查詢 v$pdbs 可以分辨哪些是普通 PDB ,哪些是 Application Root 或是 Application PDB :

SQL> select name,APPLICATION_ROOT,APPLICATION_PDB from v$pdbs


Application Root 之所以能夠與 Application PDB 共享物件靠的就是一個名為 application 的東西,在建立完 Application Root 之後必須建立一個 application ,然後在此 application 之下部屬所需要的物件,那麼就可以透過 application 這個機制將東西 sync 到底下的 Application PDB 。在第一次建立 application 使用 begin install 、 end install :

A screenshot of a computer program

AI-generated content may be incorrect. 

之後於 Application PDB 進行 sync 就可以看到 Application Root 所部屬的物件 :

A screen shot of a computer

AI-generated content may be incorrect.

 

在 application 執行的所有動作都會記錄在 dba_app_statements 裡面,當執行 sync 時會將 dba_app_statements 所記錄的動作重新在 Application PDB 執行一次。

如果要進行異動就必須針對 application 進行變更,變更的方式可以使用 begin upgrade 或者是 begin patch ,差別在於 begin upgrade 必須變更版本號碼,執行 begin upgrade 的同時 Application Root 會自動 Clone 一份出來保留舊版本以便回退版本時需要;而 begin patch 則是不用進行版本號的變更,而且 Application Root 也不會進行 Clone 。例如針對剛剛建立的 HR 新增一個 view :

A black screen with white text

AI-generated content may be incorrect.


執行 begin upgrade 之後會看到一個 Application Root 的 Clone :

A black screen with white text

AI-generated content may be incorrect. 


隨著 application 的異動,有可能產生越來越多個 Clone PDB 進而占用空間,如果確認不會再回退到舊的 application 版本,可以使用 set compatibility version 選擇要保留到哪一個版本,這樣就會自動清理掉被 Clone 出來的 Application Root 了 :

SQL> alter session set container=pdb_root;

不保留舊版本

SQL> alter pluggable database application app1 set compatibility version current;

保留到 1.2 版本

SQL> alter pluggable database application app1 set compatibility version '1.2';


由 alert log 可以看出執行 set compatibility version 之後自動將 Clone 的 PDB 刪除了 :

A screenshot of a computer program

AI-generated content may be incorrect. 

透過 dba_applications 可以查詢目前有哪些 application 以及目前的版本,在 Application Root 建立之後會有一個預設的 application ,其 app_implicit 為 Y ,其餘 application 的 app_implicit 為 N :

A screen shot of a computer

AI-generated content may be incorrect.


這邊要注意的是,如果建立使用者不是在 begin install/upgrade 建的,那麼這個使用者就會被歸類在預設的 application ,也就是 IMPLICIT USER ,如果在 begin install/upgrade 建的,那麼這個使用者就會是屬於當下 application 的一部分,也就是 NON-IMPLICIT USER :

A black screen with white text and red arrows

AI-generated content may be incorrect. 

對於 NON-IMPLICIT USER 的異動就必須要進行 application upgrade/patch ,否則就會出現 ORA-65274: operation not allowed from outside an application action 這個錯誤。


除了建立使用者之外,在 begin install/upgrade 建立的物件稱作 Application Common Object ,總共有三種類型 :

  • METADATA-LINKED : 只有物件的結構定義屬於 Root , PDB 可以對此 Table 進行任何 DML 的操作。

  • DATA-LINKED : 物件的結構與資料的權限均屬於 Root , PDB 不可以對 DATA-LINKED 的 Table 進行任何 DML 的操作。

  • EXTENDED DATA-LINKED : PDB 可以對此 Table 進行任何 DML 的操作,但是不能更新原本就已經存在 Root 的資料。


預設類型由參數 default_sharing 決定,這個參數預設為 metadata 。在 create table 的語法中加入 sharing 就可以指定類型,沒有使用 sharing 則會套入 default_sharing ,例如 :

建立 data-linked object 

SQL> create table hr.region_s sharing=data (region_id number, region_name varchar2(20));

建立 extended data-linked object

SQL> create table hr.region_es sharing=extended data (region_id number, region_name varchar2(20));


PDB 如果嘗試對 DATA-LINKED OBJECT 進行 DML ,則會出現錯誤 :

A black screen with white text

AI-generated content may be incorrect.

如果是 EXTENDED DATA-LINKED , PDB 要更新原本已經存在 Root 的資料,不會允許更新但也不會報錯 :

A black screen with white text

AI-generated content may be incorrect.

透過 METADATA-LINKED 的特性可以做到類似 sharding 的功能,在這邊稱作 container map ,意思是每個 PDB 都有擁有一個 partition 的資料,在 root 查詢這個table 會自動到相對應的 PDB 撈取這部分的資料 :

A diagram of a application

AI-generated content may be incorrect.

例如建立一個 country 的 table , pdb_app1 與 pdb_app2 存放不同 country 的資料 :

PDB Name

Partition Name

Data

pdb_app1

pdb_app1

CN,JP,TW,HK

pdb_app2

pdb_app2

US,CA,FA,UK


首先於 Application Root 建立 Table country 為 METADATA LINK :

SQL> alter pluggable database application app1 begin upgrade to '1.4';

SQL> create table hr.country SHARING=METADATA (c_id number,pdb_app varchar2(20),c_name varchar2(20));


建立 map table 以及 enable container map :

SQL> create table hr.country_map (pdb_app varchar2(20) not null) partition by list (pdb_app)(partition pdb_app1 values ('pdb_app1'),partition pdb_app2 values ('pdb_app2'));

SQL> alter table hr.country enable container_map;

SQL> alter table hr.country enable containers_default;

SQL> alter pluggable database application app1 end upgrade to '1.4';


於 pdb_app1 sync 然後 insert data :

SQL> alter session set container=pdb_app1;

SQL> alter pluggable database application app1 sync;

SQL> insert into hr.country values (1,'pdb_app1','CN');

SQL> insert into hr.country values (2,'pdb_app1','JP');

SQL> insert into hr.country values (3,'pdb_app1','TW');

SQL> insert into hr.country values (4,'pdb_app1','HK');

SQL> commit;


於 pdb_app2 sync 然後 insert data :

SQL> alter session set container=pdb_app2;

SQL> alter pluggable database application app1 sync;

SQL> insert into hr.country values (1,'pdb_app2','US');

SQL> insert into hr.country values (2,'pdb_app2','CA');

SQL> insert into hr.country values (3,'pdb_app2','FA');

SQL> insert into hr.country values (4,'pdb_app2','UK');

SQL> commit;


設定完畢之後從 Application Root 查詢資料,就會自動去對應的 PDB 撈取資料 :

SQL> alter session set container=pdb_root;

SQL> select * from hr.country where pdb_app='pdb_app1';

SQL> select * from hr.country where pdb_app='pdb_app2';

A screen shot of a computer

AI-generated content may be incorrect. 

Application Container 在架構上頗為複雜,在應用上需要規劃好 AP 以及 DB 的架構後再來使用。