Oracle 從 12c 開始推出了 Multitenant 架構,有別於以往 1個 Instance = 1 個 Database , Multitenant 則是 1個 Instance 可以建立多個 Database ,這個 Instance 所屬的 Database 就稱為 Container Database ,簡稱 CDB ,而 CDB 之上可以再建立多個 Database ,這些 Database 稱為 Pluggable Database , 簡稱 PDB 。
CDB 的角色只是作為 PDB 的一個載體,不存放任何 user data ,而 PDB 才是 user data 與應用系統所使用的資料庫,也就是以往使用者所用的資料庫(Non-CDB) 變成現在要使用 PDB ,雖然 PDB 都是建立在 CDB 之上,不過每個 PDB 都是獨立的資料庫且互不影響, PDB 對於使用者來說使用上與以往 Non-CDB 並無不同,差別只在於 DBA 的管理方式不同而已。
Multitenant 架構的優點是將資料庫集中化管理,傳統 Non-CDB 架構下, DBA 必須管理多個 Database Instance ,而在 Multitenant 架構下 DBA 只需管理一個 CDB Instance ,所有的 DB (PDB) 都屬於這個 CDB Instance ,不再需要切換 ORACLE_SID 去登入每個 DB 了。除此之外, PDB 可以快速的建立,對於 DBA 來說要部屬新的資料庫或是要建立測試資料庫都非常方便,而且 PDB 也可以根據需求使用 unplug-plug 或是 clone 的方式來移轉到其它 CDB ,使用上更有彈性。
Multitenant 架構下只有 CDB 有 Background Process , CDB 本身做為 Root Container ,基於Root Container 底下建立 PDB ,每個 PDB 都有自己獨立的 Data file ,不過 Control file 與 Redo Log 只存在 CDB root ,所有 PDB 共享一份 Control file 與 Redo Log Group :
透過 DBCA 就可以建立 CDB ,只要將 Create as Container Database 選項勾選起來就可以將資料庫建立為 Multitenant 架構 :
如果選擇以 Customer 的方式建立資料庫,那麼就可以選擇 CDB 與 PDB 所要安裝的 Components :
由於不確定未來要 Plug 到此 CDB 的 PDB 具有哪些 components ,因此建議 CDB 在建立時把所有的 components 都裝上,而勾選是否 Include in PDBs 則會影響 PDB Seed , PDB Seed 的用途是做為建立新 PDB 的一個 Template ,如果 PDB Seed 沒有安裝某些 component ,那麼未來透過 PDB Seed 所建立新的 PDB 也不會有這些 component 。
使用 show con_id 可以判斷這個 DB 是否為 Multitenant 架構,如果為 0 表示為 Non-CDB ,為 1 表示為 Container Database , show con_name 可以顯示目前所在的 PDB 名稱,如果在 CDB 則會顯示 CDB$ROOT :
使用 show pdbs 或者是查詢 v$pdbs 可以查詢目前 CDB 中有哪些 PDB :
PDB 在正常開啟的狀態為 READ WRITE ,如果是關閉的狀態則是 MOUNTED , PDB$SEED 做為建立 PDB 的 Template ,狀態則一直都會是 READ ONLY 。
PDB 建立之後預設的 Service 名稱就是這個 PDB 的名稱, PDB 的連線方式與傳統 DB 的連線方式無異,透過 tnsnames 就可以連線到 PDB ,如果要直接以 sqlplus / as sysdba 的方式連線至 PDB ,則需設置 ORACLE_PDB_SID 即可 :
如果登入到 CDB 要進入某個 PDB 則使用 alter session set container 來切換:
一個 CDB 可以容納多少個 PDB 由 CDB 參數 max_pdbs 決定,最多可設置到 4098 。
由於 CDB 不存放 user data ,所以不能建立一般的使用者,只能建立 Common User , Common User 的特性就是在 CDB 建立之後,所有的 PDB 都一併會建立此使用者,建立 Common User 必須在使用者名稱前面加上 C## , C## 為 Common User 的一個識別符號,由參數 common_user_prefix 設定,預設為 C## ,建立方式與傳統使用者建立的方式相同,只需帶上 C## 就表示為 Common User ,同理 drop C## 這個 Common User 的時候所有 PDB 也會一併刪除 :
如果不帶上 C## 表示為一般使用者則會出現 ORA-65096 錯誤 :
雖然 Common User 會建立在 CDB 與所有 PDB 上,但是對於 Common User 的權限授予使可以分開授權的,在 grant 語法中加上 container 就可以分開授權,例如 Common User 在所有 PDB 都具有這個權限則使用 container=all ;若是只有在這個 PDB 才有這個權限,則使用 container=current :
最後提一下 DBA 在管理上多了 CDB_ 開頭的 view 可以查詢,例如以往所查詢的 dba_users 、 dba_tables 、 dba_objects …等都有相對應的 cdb_ view 可以查詢,例如 cdb_users 、 cdb_tables 、 cdb_objects …等,差別在於 cdb_ 開頭的 view 多了一個 con_id 的欄位,也就是 DBA 只要在 CDB 層級就可以查詢底下所有 PDB 的物件,不須使用 alter session set container 進到每個 PDB 進行查詢 :
若是在 PDB 層級使用 cdb_ 開頭的 view ,則只會顯示這個 PDB 本身的物件,不會顯示其它 PDB :
由於 Multitenant 架構未來可能會成為 Oracle 資料庫的主要架構,身為 Oracle DBA 必須熟悉如何管理與使用 Container Database 。