2021年10月5日 星期二

11.2 RMAN

RMAN 是 Oracle 用來備份的主要工具,最早起源於 Oracle 8i ,直到目前已經是 Oracle 資料庫主要的備份方式了,不論是冷備份或是熱備份都可以使用 RMAN 來達成, RMAN 進行冷備份必須將資料庫開啟至 mount 狀態下再進行備份,由於資料庫需重新啟動至 mount ,此時不如將資料庫 shutdown 後直接將檔案 copy 備份起來比較直觀,因此很少用 RMAN 來進行冷備份,多數的情況下都是在資料庫運行的過程中,使用 RMAN 來做一個熱備份。RMAN 取代了傳統使用 alter database begin backup 的方式,將備份統一由 RMAN 的介面單一完成,不須像 begin backup 那樣要使用作業系統命令來 copy 資料庫檔案,而且只要撰寫好一個腳本便可以適用所有的資料庫。


透過 RMAN 連線到資料庫便可以進行備份與還原的動作,使用 " rman target / " 或者是 " rman 帳號/密碼@<db_tnsnames> " 就可以進入 RMAN> 的提示符號下進行作業, RMAN 的指令大致上可以作為以下分類:


1. 連線指令: "connect" ,例如 "connect target /" 、 "connect catalog rman/rman@rman" 、 "connect auxiliary sys/welcome1@stby" 。


2. SQL 指令: "sql" ,主要用途是在 RMAN> 介面底下執行 SQL 指令,只需在前面加上 "sql" 就可以執行 SQL 指令,例如 "SQL 'ALTER SYSTEM ARCHIVE LOG CURRENT';" 。到了 Oracle 12c 之後, RMAN> 介面可以直接執行 SQL 指令了,不須再加上 "sql" 。


3. 設定 RMAN 參數指令: "configure" ,例如設定 archive log 清理規則 "configure archivelog deletion policy to shipped to all standby" 。


4. 顯示設定內容: "show" ,例如顯示目前 RMAN 所有設定 "show all" 。


5. 備份還原相關指令: 備份 "backup" 、 還原 "restore" ,復原 "recover" ,其中 "restore" 指的是把 Data File 還原回來;而 "recover" 則是用來 apply archive log 。


6. 管理相關指令: "list" 列出備份相關資訊,例如 "list backup of database" ; "report" 用來分析備份與還原資訊,例如列出超過 retention policy 的備份 "report obsolete" 、 列出需要備份的檔案 "report need backup" ; "crosscheck" 用來檢查實際上存在於作業系統的備份檔案與資料庫所記錄的備份資訊是否相符,如果不相符,那麼那些紀錄將會被標示為 expired ,例如 "crosscheck backup" 、 "crosscheck archivelog all" 。


RMAN 指令執行的方式可分為兩種,一種是直接在 RMAN> 底下執行,另外一種是使用批次方式執行,所有命令必須寫在 RUN{} 底下這個區塊。


RMAN 可以將資料庫備份到作業系統的 filesystem ,或者是直接備份到磁帶,在執行備份前必須使用 "allocate channel" 來告訴 RMAN 要備份到哪裡,如果是備份到 filesystem 則執行 "allocate channel ch1 type disk" ;如果是備份到磁帶,則是 "allocate channel ch1 type sbt_tape" ,一個 channel 代表一個 RMAN 的 process ,我們可以 allocate 多個 channel 來讓 RMAN 使用多個 process 來進行備份或還原的任務。


一個完整的 RMAN 資料庫備份必須包含 Data File 、 Control File 、 Archive Log 與 Spfile ,例如備份到 filesystem :

$ rman target /

RMAN> run {

 crosscheck backup;

 crosscheck archivelog all;

 allocate channel ch1 type disk;

 allocate channel ch2 type disk;

 backup database format '/opt/app/dump/rman/fulldb_%s_%t.bak';

 sql 'alter system archive log current';

 backup archivelog all format '/opt/app/dump/rman/archivelog_%t_%s.bak' delete input;

 backup current controlfile format '/opt/app/dump/rman/controlfile_%s_%t.bak';

 backup spfile format '/opt/app/dump/rman/spfile_%t_%s.bak';

 release channel ch1;

 release channel ch2;

}        


其中 %s 用來設定 backup set 的編號; %t 為 backup set 加上時間戳記;備份 Archive Log 可加上 delete input 指令,用途是在備份完成後將 Archive Log 刪除。


如果是備份到磁帶的話,則需將 channel 設定為 type sbt_type ,例如透過 NBU 來做備份:

$ rman target /

RMAN> run {

 allocate channel ch1 type sbt_tape;

 allocate channel ch2 type sbt_tape;

 send 'NB_ORA_SERV=nbubak,NB_ORA_CLIENT=oradb1';

 backup database format '/opt/app/dump/rman/fulldb_%s_%t.bak';

 release channel ch1;

 release channel ch2;

}        


如果在 NBU 的 bp.conf 裡面有設定好 SERVER 與 CLIENT_NAME 的話,那麼在 RMAN 裡面則可以省去 "send 'NB_ORA_SERV=nbubak,NB_ORA_CLIENT=oradb1'" 這一段。


又例如透過 IBM TSM 來做備份,則設定環境變數如下:

$ rman target /

RMAN> run {

 allocate channel ch1 type sbt_tape parms

'ENV=(TDPO_OPTFILE=/usr/tivoli/tsm/client/oracle/bin64/tdpo.opt)';

 backup database format '/opt/app/dump/rman/fulldb_%s_%t.bak';

 release channel ch1;

 release channel ch2;

}        


RMAN 備份到不同廠牌的磁帶機設定都略有不同,大體上都是提供磁帶機 library 的位置給 RMAN 就可以備份到磁帶上面。


RMAN 除了做 full database backup 之外,也可以進行 incremental backup ,使用 incremental backup 必須賦予一個 backup level <號碼> ,這個 backup level 是用來對備份做一個旗標,用來告訴 RMAN 需要 incremental backup 的範圍在哪裡,所以在進行 incremental backup 之前必須要做一次 full backup ,往後的備份才有 incremental 的基準,在這邊做 full backup 時必須要特別指定 incremental level 0 ,有了這個 level 0 之後才可以進行 incremental backup:

$ rman target /

RMAN> run {

 allocate channel ch1 type disk;

 backup incremental level 0 database format '/orabak/fulldb_%s_%t.bak';

 release channel ch1;

 }        


有了 incremental level 0 之後就可以進行 incremental backup ,有兩種模式 Differential Incremental Backup 與 Cumulative Incremental Backup 。 Differential 模式所 incremental 的區間為 incremental level 小於或等於前一個 level ;而 Cumulative 模式所 incremental 的區間只有抓與小於前一個 level 。例如每日所設定的 incremental level 如下:


週日進行 incremental level 0 的全備份,週一、二、四、五設定為 incremental level 2 ,週三與週六設定為 incremental level 1 。對於週一來說,它只需找前一個比它 level 小的來作為 incremental 區間,所以週一會備份 incremental 週日 ~ 週一這個區段;對於週二來說,它的設定為 incremental level 2 ,在 Differential 模式下,它會找前一個與它相同或是小於它的 level 來做 incremental 區間,週一同樣為 level 2 ,所以它會 incremental 週一 ~ 週二這段區間 (綠色部分) ,而在 Cumulative 模式下,它只會找前一個比它小的 level ,所以它會 incremental 週日 ~ 週二這段區間 (紅色部分) ,後面以此類推。


預設為 Differential 模式,備份時只需提供 incremental level 就好:

$ rman target /

RMAN> run {

 allocate channel ch1 type disk;

 backup incremental level 2 database format '/orabak/fulldb_%s_%t.bak';

 release channel ch1;

 }        


如果要使用 Cumulative 模式,則需要加上 Cumulative 關鍵字:

$ rman target /

RMAN> run {

 allocate channel ch1 type disk;

 backup incremental level 2 cumulative database format '/orabak/fulldb_%s_%t.bak';

 release channel ch1;

 }


一個完整的資料庫還原,必須逐步的還原 Spfile 、 Control File 與 Data File ,最後再 apply 所需的 archive log , RMAN 提供了特殊的啟動指令 "startup force nomount" ,有了這個指令可以不需要任何的參數檔暫時的啟動 Database Instance ,透過這個暫時的啟動,我們就可以用來還原參數檔 spfile ,還原完 spfile 再正常地將 instance 啟動至 nomount :

$ rman target /

RMAN> startup force nomount;

RMAN> restore spfile from '/orabak/spfile_20211004_470aonnu_1_1';

RMAN> shutdown immediate

RMAN> startup nomount


還原完 spfile 之後,接下來必須要還原 Control File ,由於資料庫的備份資訊都存放在 Control File 裡面,所以必須將 Control File 還原,有了備份資訊,接下來系統才能夠逐步找到備份檔來還原 Data File :

RMAN> restore controlfile from '/orabak/controlfile_132_1085038213';

RMAN> alter database mount;


順帶一提,如果是使用 NBU 備份,則可以使用 NBU 命令 "bplist -t 4 -l -R /" 來檢視備份檔。


還原完 Control File 之後,就可以簡單執行 restore 與 recover 命令來還原整個資料庫,此時系統就會自動的從 Control File 裡面所記錄的備份資訊抓取所需的備份檔來還原:

RMAN> restore database;

RMAN> recover database;


更進階一點,可以使用 set 指令來指定要還原到哪個時間點或 scn , set 指令必須放入 RUN{} 裡面來執行:

RMAN> run {

set until scn 99410585;

restore database;

recover database;

 }

  (指定還原到哪個 SCN)

RMAN> run {

set until time "to_timestamp('20211005 17:00:00','yyyymmdd hh24:mi:ss')";

restore database;

recover database;

 }

  (指令還原到哪個時間點)


還原完畢後就可以將資料庫開啟,完成整個步驟:

$ sqlplus / as sysdba

SQL> alter database open resetlogs;


由於備份紀錄存放在 Control File 當中,因此 Control File 顯得相對重要,如果 Control File 遺失,那麼很有可能就無法還原整個資料庫,為了避免這個問題,我們可以建立一個 Catalog DB ,將備份的紀錄存放在 Catalog DB 當中,如此一來等於多添加了一份保險。


建立 Catalog DB ,實際上就是建立一個 DB ,然後把經由 RMAN 備份的資料庫的備份資訊存放在這個 DB 當中,一個 Catalog DB 可以存放多個 DB 的備份資訊,這邊要注意的是, Catalog DB 的字元集必須要是這些 DB 的 Superset ,且資料庫版本必須要大於或等於這些 DB ,例如經由 RMAN 備份的 DB 有 11.2.0.2 、 10.2.0.4 、 12.1.0.1 …等版本,那麼在 Catalog DB 建置的挑選上,就要選擇使用 12.1.0.1 的版本。


建置 Catalog DB ,首先必須先創立一個 Catalog 的使用者,並授予recovery_catalog_owner 的權限,例如創建一個使用者 RCAT作為 Catalog 的使用者:

SQL> create user rcat identified by welcome1 default tablespace users;

SQL> grant connect,resource,recovery_catalog_owner to rcat;


使用者創建完成後,接下來要創建 Catalog 所使用的物件,使用 RMAN 登入 Catalog DB ,並執行 create catalog 建立物件,這樣就完成 Catalog DB 的建置:

$ rman catalog rcat/welcome1@catalogdb

RMAN> create catalog;


建置完 Catalog DB 後,接下來就是要把需要存放備份資訊的 DB 註冊進來,例如將 orcl 這個資料庫註冊到 Catalog DB:

$ export ORACLE_SID=orcl

$ rman target / catalog rcat/welcome1@catalogdb

RMAN> register database;


註冊完成後,可執行 report schema 來檢查,如果有列出此 DB 的相關資訊,那麼就表示有註冊成功:


有了 Catalog DB 後,那麼在備份的同時就可以將備份紀錄存放到 Catalog DB 當中:

$ rman target / catalog rcat/welcome1@catalogdb

RMAN> run {

 allocate channel ch1 type disk;

 backup incremental level 0 database format '/orabak/fulldb_%s_%t.bak';

 release channel ch1;

 }        


對於資料庫還原來說,我們只需要藉由 Catalog DB 把 Control File restore 回來:

$ rman target / catalog rcat/welcome1@catalogdb

RMAN> startup nomount;

RMAN> restore controlfile;

RMAN> alter database mount;

RMAN> exit;

$ rman target /

RMAN> restore database;

RMAN> recover database;

RMAN> alter database open resetlogs;


Control File 還原回來後,因為所有的備份資訊 Control File 都有紀錄,因此接下來的還原過程就不需要 Catalog DB 了。


目前 RMAN 已經是 Oracle 資料庫最主要的備份還原方式了, DBA 必須要對這項工具非常熟悉才行。



3 則留言:

  1. 想請教,公司是使用oracle 11.2,目前僅有在每週六用rman做一次full backup,萬一資料庫在3天後crash,這時手頭上只有前一週六的backup資料及這幾天的archive log,是否能將資料庫還原至crash前的狀態?感謝!

    回覆刪除
    回覆
    1. 是的,可以使用週六的 full backup 加上這中間幾天的 archive log 來還原至 crash 前的狀態,recover database 會開始尋找需要的 archive log 序號,如果中間有缺少的話便會停止,如果平日不進行資料庫備份的話,也建議針對 archive log 進行備份。

      刪除
    2. 經過測試果然可行,也將每日archive log備份納入排程了,非常感謝

      刪除