2025年11月25日 星期二

8. Pluggable Database 備份與還原

  • Backup

Pluggable Database 備份的方式與傳統的 Non-CDB 備份方式無異,不同的是 Multitenant 架構下

有分為 CDB 的備份與 PDB 的備份,一般情況下於 CDB 層級執行 backup database 會將 CDB 以及

底下的所有 PDB 一起備份,例如於 CDB 執行 full backup ,包含 CDB$ROOT 以及全部的 PDB 都會

一起備份 :

$ rman target /

RMAN> 

run {

crosscheck backup;

crosscheck archivelog all;

allocate channel ch1 type disk;

allocate channel ch2 type disk;

delete noprompt obsolete;

backup database format '/u02/backup/fulldb_%s_%t';

sql 'alter system archive log current';

backup archivelog all format '/u02/backup/archivelog_%t_%s_%p' delete input;

backup current controlfile format '/u02/backup/controlfile_%s_%t';

backup spfile format '/u02/backup/spfile_%T_%U';

release channel ch1;

release channel ch2;

}


 如果只要備份 PDB 可以使用 backup pluggable database 單獨備份 PDB :

備份 Pluggable database PDB1 :

RMAN> backup pluggable database pdb1 format '/u02/backup/pdb1_%s_%t';

備份 CDB$ROOT 與 PDB1 :

RMAN> backup pluggable database "CDB$ROOT",PDB1 format '/u02/backup/pdb1_%s_%t';


由於 PDB 必須要有外層的 CDB 才能夠存在,因此備份的時候比較不會只單獨備份 PDB ,

至少會備份 CDB$ROOT 加上所需要的 PDB ,這樣還原的時候才不會因為沒有 CDB$ROOT 

造成 PDB 無法還原。


如果是需要 Duplicate 整個 CDB ,可以使用 skip pluggable database 排除某些 PDB 不要進行 duplicate ,

不一定整個 CDB 底下的所有 PDB 都進行 duplicate :

Duplicate CDB 排除 PDB_ROOT,PDB_APP1,PDB_APP2 :

$ rman target /

RMAN> connect auxiliary sys/welcome1@cdb2

run {

 allocate auxiliary channel ch1 type disk;

 allocate auxiliary channel ch2 type disk;

 duplicate database to cdb2;

 skip pluggable database PDB_ROOT,PDB_APP1,PDB_APP2;

 nofilenamecheck;

 }


  • Restore

Restore 整個 CDB 的方式與原本還原 Non-CDB 的方式無異。如果只是將 PDB restore 至原本的 CDB 

只需要簡單的執行 restore pluggable database 就可以了 :

還原 PDB2 至原本的 CDB :

$ sqlplus / as sysdba

SQL> alter pluggable database pdb2 close abort;

$ rman target /

RMAN> restore pluggable database pdb2;

RMAN> recover pluggable database pdb2;

RMAN> exit;

$ sqlplus / as sysdba

SQL> alter pluggable database pdb2 open;


這邊要注意的是,如果執行了 drop pluggable database 命令之後,就沒有辦法簡單的使用 restore 來還原了,

例如執行了 drop pluggable database PDB2 將 PDB2 drop ,此時就無法直接 restore 了,因為執行了 drop 

命令之後,這個 PDB 的 metadata 已不存在 CDB ,此時如果再執行 restore pluggable database 便會出現 

RMAN-06813: could not translate pluggable database PDB2 錯誤 :

A screen shot of a computer screen

AI-generated content may be incorrect.


這個時候只能使用 PDB PITR (Point In Time Recovery) 來進行還原,它的原理是利用備份先還原到 

auxiliary destination ,然後再將 PDB unplug / plug 回來,例如使用 PITR 來還原 PDB2 :

還原 PDB2 至原本的 CDB :

$ rman target /

RMAN> run {

set until time "to_timestamp('20251124 16:40:00','yyyymmdd hh24:mi:ss')";

recover pluggable database pdb2 auxiliary destination='/u02/auxiliary';

alter pluggable database pdb2 open resetlogs;

}


這邊要注意的是,設定 until time 的時間必須要有 CDB$ROOT 與 PDB2 的備份,並且 auxiliary destination 

的空間必須要可以容納 CDB$ROOT + PDB2 才行。


  • Flashback

最後來說一下 flashback database , PDB 可以單獨執行 flashback database ,只要於 CDB 層級有

 enable flashback database 功能即可,首先於 CDB 層級啟用 flashback :

SQL> show con_name

CON_NAME

------------------------------

CDB$ROOT


SQL> alter system set db_recovery_file_dest_size=30G;

SQL> alter system set db_recovery_file_dest='/u01/recovery_area';

SQL> SQL> alter database flashback on;


例如於 PDB2 建立 restore point 以及單獨進行 flashback :

建立 restore point :

SQL> alter session set container=pdb2;

SQL> create restore point rp_2025 guarantee flashback database;

執行 flashback database :

SQL> alter session set container=pdb2;

SQL> alter pluggable database close immediate;

SQL> flashback pluggable database to restore point rp_2025;

SQL> alter pluggable database open resetlogs;


總結 Multitenant 的備份與傳統的 Non-CDB 備份差異不大, DBA 只需要注意 PDB 必須連同其所在的 

CDB$ROOT 一起備份即可。


 

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 的架構後再來使用。

2025年9月26日 星期五

6. Data Guard on Multitenant Database

Multitenant Database 的 Data Guard 建置方式與傳統 Non-CDB 的建置方式無異,在 Oracle 12c 至 19c 的

版本只能於 CDB 層級來建置 Data Guard ,自 Oracle 21c 之後就可以只在 PDB 層級建置 Data Guard 。


在 CDB 層級建立 Data Guard 之後需要探討的問題是,未來在此 CDB 上建立新的 PDB 是否會同步到 standby 

端 ? 以下分別說明同步與不會同步的兩種情境 :

  • PDB 自動同步至 Standby 的情境

有兩個情境在 Primary 建立新 PDB 時會自動同步到 Standby :

1. Create PDB from seed

於 Primary 使用 seed 建立新的 PDB 時,所有的操作會自動同步到 Standby 端,例如在 Primary 建立 pdb3 

會自動同步到 Standby :

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


在 Standby 的 alter log 可以看到新的 PDB3 自動被建立出來 :

A screenshot of a computer program

AI-generated content may be incorrect.

如果這個情境下反而不想同步到 Standby 端,那麼在 create pluggable 的語法當中加上 STANDBYS=NONE 

就不會同步了。


2. Clone PDB from Read-Only PDB

如果是以 clone 的方式建立 PDB ,則來源端 PDB 必須為 Read-Only 才能夠自動同步到 Standby ,

例如 Create PDB4 from Local PDB3 ,此時 PDB4 會自動同步到 Standby :

SQL> alter pluggable database pdb3 close immediate;

SQL> alter pluggable database pdb3 open read only;

SQL> create pluggable database pdb4 from pdb3 file_name_convert=('pdb3','pdb4');


在 Standby 的 alter log 可以看到新的 PDB4 自動被建立出來 :

A screenshot of a computer program

AI-generated content may be incorrect.


如果是 Clone from Remote PDB 則限制較多,除了要求 Remote PDB 必須為 Read only 之外, 

Standby Database 必須為 ADG 且設定參數 standby_pdb_source_file_dblink 才會自動同步,

例如 Create rpdb from Remote Clone :

Enable ADG on Standby :

SQL> shutdown immediate

SQL> startup mount

SQL> alter database open read only

SQL> alter database recover managed standby database disconnect;

SQL> alter system set standby_pdb_source_file_dblink='rcdb';


Create PDB from Remote on Primary :

SQL> create pluggable database rpdb from rpdb@rcdb file_name_convert=('SQLMGMT/rpdb','ORAPDB/rpdb');


在這個情境下比較特殊, Standby 實際上是透過 DB Link 直接去 Remote Source PDB 拉 datafile 

而非從 Primary 拉,standby_pdb_source_file_dblink 設定的是連線到 Source Database 的 DB Link 名稱

,而且此 DB Link 必須要能夠連線成功,如果設定都沒錯的話 Standby 就會自動同步建立此 PDB :

A screenshot of a computer program

AI-generated content may be incorrect.


如果此時 Standby 沒有啟用 ADG ,則會因為無法使用 DB Link 來 restore datafile 造成 MRP crash :

A screenshot of a computer program

AI-generated content may be incorrect.

此時必須先將新建的 PDB disable recovery 才能夠重新啟用 MRP :

SQL> alter session set container=rpdb;

SQL> alter pluggable database disable recovery;

SQL> exit;

$ sqlplus / as sysdba

SQL> alter database recover managed standby database disconnect;



  • PDB 不會同步至 Standby 的情境

使用 Clone 的方式建立 PDB 不論是從 Local Clone 或是 Remote Clone ,只要 Source PDB 不是 Read Only 的情況下

,新建的 PDB 就不會自動同步至 Standby ,此時必須手動針對新的 PDB 進行 restore 並且 enable recovery ,

例如 Create wpdb from Read Write pdb :

SQL> create pluggable database wpdb from wpdb@rcdb file_name_convert=('SQLMGMT/wpdb','ORAPDB/wpdb');

SQL> alter pluggable database wpdb open;


此時 Standby 端只會建立 Metadata 不會 restore datafile ,也就是此時 Standby 端只有 wpdb 的空殼而已 :

A screenshot of a computer screen

AI-generated content may be incorrect.

此時必須於 Standby 端進行 restore pluggable database :

$ rman target /

RMAN>  run {

set newname for datafile 112 to '/u01/oradata/ORAPDBS/wpdb/system01.dbf';

set newname for datafile 113 to '/u01/oradata/ORAPDBS/wpdb/sysaux01.dbf';

set newname for datafile 114 to '/u01/oradata/ORAPDBS/wpdb/undotbs01.dbf';

restore pluggable database wpdb from service orapdb;

switch datafile 112 to copy;

switch datafile 113 to copy;

switch datafile 114 to copy;

}


Restore 結束後必須再 enable recovery 才能夠同步 :

$ sqlplus / as sysdba

SQL> alter database recover managed standby database cancel;

SQL> alter session set container=wpdb;

SQL> alter pluggable database enable recovery;

SQL> exit;

$ sqlplus / as sysdba

SQL> alter database recover managed standby database disconnect;


 

除此之外,如果在 Primary 針對 PDB 進行 flashback 的操作, Standby 端也會同步針對這個 PDB 進行 flashback ,

例如於 Primary 端針對 PDB2 進行 flashback ,首先必須於 Standby 端確認 Standby 有啟用 flashback 功能 :

A black screen with white text

AI-generated content may be incorrect.

從 Primary 針對 PDB2 進行 flashback 的操作 :

SQL> alter pluggable database pdb2 close immediate;

SQL> flashback pluggable database pdb2 to restore point rp;

SQL> alter pluggable database pdb2 open resetlogs;


在 pdb2 open resetlogs 的同時可以看到 Standby 端同步進行了 flashback 的動作 :

A screenshot of a computer

AI-generated content may be incorrect.

Data Guard 在有 CDB/PDB 的情況下較為複雜, DBA 在日常維運上必須要非常了解這些情境。