Application Container 是在 Multitenant 中的一種特殊的架構,在既有的 CDB 下建立一個 PDB 作為 Application Root,可以說是在 CDB Root 底下再產生一個 Root ,然後 Application Root底下再建立 Application PDB :
建立 Application Root 的用意在於 Application Root 可以與底下的 Application PDB 共享物件,在進行程式部屬或者是更版只需要在 Application Root 進行變更,之後將異動 sync 到底下的 PDB 就好,優點就是同樣的變更無需要每個 PDB 都重複做一次 :
在建立 PDB 的語法當中加上 as application container 就可以將 PDB建立成為 Application Root :
在 PDB Root 底下建立的 PDB 即為 Application PDB :
於 CDB 層級查詢 v$pdbs 可以分辨哪些是普通 PDB ,哪些是 Application Root 或是 Application PDB :
Application Root 之所以能夠與 Application PDB 共享物件靠的就是一個名為 application 的東西,在建立完 Application Root 之後必須建立一個 application ,然後在此 application 之下部屬所需要的物件,那麼就可以透過 application 這個機制將東西 sync 到底下的 Application PDB 。在第一次建立 application 使用 begin install 、 end install :
之後於 Application PDB 進行 sync 就可以看到 Application Root 所部屬的物件 :
在 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 :
執行 begin upgrade 之後會看到一個 Application Root 的 Clone :
隨著 application 的異動,有可能產生越來越多個 Clone PDB 進而占用空間,如果確認不會再回退到舊的 application 版本,可以使用 set compatibility version 選擇要保留到哪一個版本,這樣就會自動清理掉被 Clone 出來的 Application Root 了 :
由 alert log 可以看出執行 set compatibility version 之後自動將 Clone 的 PDB 刪除了 :
透過 dba_applications 可以查詢目前有哪些 application 以及目前的版本,在 Application Root 建立之後會有一個預設的 application ,其 app_implicit 為 Y ,其餘 application 的 app_implicit 為 N :
這邊要注意的是,如果建立使用者不是在 begin install/upgrade 建的,那麼這個使用者就會被歸類在預設的 application ,也就是 IMPLICIT USER ,如果在 begin install/upgrade 建的,那麼這個使用者就會是屬於當下 application 的一部分,也就是 NON-IMPLICIT USER :
對於 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 ,例如 :
PDB 如果嘗試對 DATA-LINKED OBJECT 進行 DML ,則會出現錯誤 :
如果是 EXTENDED DATA-LINKED , PDB 要更新原本已經存在 Root 的資料,不會允許更新但也不會報錯 :
透過 METADATA-LINKED 的特性可以做到類似 sharding 的功能,在這邊稱作 container map ,意思是每個 PDB 都有擁有一個 partition 的資料,在 root 查詢這個table 會自動到相對應的 PDB 撈取這部分的資料 :
例如建立一個 country 的 table , pdb_app1 與 pdb_app2 存放不同 country 的資料 :
首先於 Application Root 建立 Table country 為 METADATA LINK :
建立 map table 以及 enable container map :
於 pdb_app1 sync 然後 insert data :
於 pdb_app2 sync 然後 insert data :
設定完畢之後從 Application Root 查詢資料,就會自動去對應的 PDB 撈取資料 :
Application Container 在架構上頗為複雜,在應用上需要規劃好 AP 以及 DB 的架構後再來使用。