在搭建Data Guard的時候,我們可以直接從主庫生成一個備庫控制檔案,或者拷貝一個備庫的控制檔案即可,後續的工作就交給Data Guard來自動恢複完成了,尤其是使用rman備份恢複的時候,使用recover database是一氣呵成,我們無須理會其中更多的細節,當然實際上Oracle已經幫我們處理好了。
我們都知道控制檔案的備份有兩種方式,一種是鏡像,一種是trace。鏡像備份方式類似alter database backup controlfile to 'xxxxx'這樣的形式,而trace備份則類似于alter database backup controlfile to trace這樣的形式。
從不少實際的操作中,我發現鏡像的恢複方式會帶來不少的困擾,如果是一個新人來做控制檔案的恢複,可能會栽入不少坑裡。最後一番折騰可能會帶來一種直覺的感覺就是控制檔案實在太重要了,如果要恢複,操作複雜度和不完全恢複差不多。而且最讓人糾結的是,折騰一番之後,還要resetlogs的方式open資料庫,我不喜歡這種恢複方式,明明完全恢複,為什麼需要這麼多的彎路。我們可能在rman中也設定了autobackup,在11g中其實是有隐含參數來控制延遲建立,預設是5分鐘。可見控制檔案還是給很多人帶來了太多困擾。
那麼怎麼恢複控制檔案比較好呢。怎麼使得控制檔案的恢複無需resetlogs呢。其實實作起來很簡單。
我們先來看看糾結的鏡像恢複方式。首先是備份。
sys@OCP11G> alter database backup controlfile to '/home/ora11g/ctl.bak' reuse;
Database altered.
[ora11g@jeanron100 ~]$ sqlplus / as sysdba
sys@OCP11G> select *from v$controlfile;
STATUS
-------
NAME
------------------------------------------------
IS_ BLOCK_SIZE FILE_SIZE_BLKS
--- ---------- --------------
/u01/app/ora11g/oradata/ocp11g/control01.ctl
NO 16384 614
/u01/app/ora11g/flash_recovery_area/ocp11g/control02.ctl
2 rows selected.
我們手工删除控制檔案
[ora11g@jeanron100 ~]$ rm /u01/app/ora11g/oradata/ocp11g/control01.ctl
[ora11g@jeanron100 ~]$ rm /u01/app/ora11g/flash_recovery_area/ocp11g/control02.ctl
這個時候停庫會報錯,是以隻能是abort方式的斷電重新開機。
sys@OCP11G> shutdown immediate
ORA-00210: cannot open the specified control file
ORA-00202: control file: '/u01/app/ora11g/oradata/ocp11g/control01.ctl'
ORA-27041: unable to open file
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3
sys@OCP11G> shutdown abort
ORACLE instance shut down.
然後重新開機啟動到nomount
sys@OCP11G> startup nomount
然後開始還原控制檔案。
[ora11g@jeanron100 ~]$ cp /home/ora11g/ctl.bak /u01/app/ora11g/oradata/ocp11g/control01.ctl
[ora11g@jeanron100 ~]$ cp /home/ora11g/ctl.bak /u01/app/ora11g/flash_recovery_area/ocp11g/control02.ctl
接着mount就沒有問題了。
idle> alter database mount;
當然在啟庫的時候肯定會有下面的提示資訊,需要設定為resetlogs模式。
idle> alter database open;
alter database open
*
ERROR at line 1:
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
當然我們嘗試resetlogs,結果還是會有一連串的ORA錯誤抛出來。而在嘗試recover的時候會提示recover using backup controlfile
idle> recover database;
ORA-00283: recovery session canceled due to errors
ORA-01610: recovery using the BACKUP CONTROLFILE option must be done
這個時候會折騰幾次,因為歸檔中的資料變化都應用完了,資料庫不知道該從哪個redo中恢複,這個就給問題的解決鋪下了障礙。我們需要帶着一絲的運氣逐個輸入redo的路徑,快則一次搞定,滿則需要多輪驗證。
idle> recover database using backup controlfile;
ORA-00279: change 1178971 generated at 09/04/2016 02:03:43 needed for thread 1
ORA-00289: suggestion : /u01/app/ora11g/flash_recovery_area/OCP11G/archivelog/2016_09_04/o1_mf_1_25_%u_.arc
ORA-00280: change 1178971 for thread 1 is in sequence #25
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
當然費了一番周折還是提示要resetlogs
idle> alter database open;
而改進的方式就是使用trace的方式,我們在這個基礎上繼續補充,就不需要resetlogs了。
因為已經恢複了控制檔案,但是似乎控制檔案的SCN已經比資料檔案頭部要舊了。不過整體來看,資料檔案的資訊沒有變化,隻有最後的SCN的部分有一些差别,那麼我們就可以使用trace的方式來彌補。
idle> startup nomount
idle> CREATE CONTROLFILE REUSE DATABASE "OCP11G" NORESETLOGS ARCHIVELOG
2 MAXLOGFILES 16
3 MAXLOGMEMBERS 3
4 MAXDATAFILES 100
5 MAXINSTANCES 8
6 MAXLOGHISTORY 292
7 LOGFILE
8 GROUP 1 '/u01/app/ora11g/oradata/ocp11g/redo01.log' SIZE 50M BLOCKSIZE 512,
9 GROUP 2 '/u01/app/ora11g/oradata/ocp11g/redo02.log' SIZE 50M BLOCKSIZE 512,
10 GROUP 3 '/u01/app/ora11g/oradata/ocp11g/redo03.log' SIZE 50M BLOCKSIZE 512
11 -- STANDBY LOGFILE
12 DATAFILE
13 '/u01/app/ora11g/oradata/ocp11g/system01.dbf',
14 '/u01/app/ora11g/oradata/ocp11g/sysaux01.dbf',
15 '/u01/app/ora11g/oradata/ocp11g/undotbs01.dbf',
16 '/u01/app/ora11g/oradata/ocp11g/users01.dbf',
17 '/u01/app/ora11g/oradata/ocp11g/testdata01.dbf',
18 '/u01/app/ora11g/oradata/ocp11g/testdata02.dbf'
19 CHARACTER SET UTF8
20 ;
idle> recover database ;
Media recovery complete.
idle> alter database open;
這個過程中直接alter database open也沒有問題,問題引刃而解。
這個修複的過程讓我想起來MySQL中的GTID,就是一個全局的标記位。使得搭建slave的時候更加省心,大多數情況其實我們也不需要知道更細節的SCN,交給MySQL自己去判斷就好。對于Oracle的恢複來說也是如此,我們可以借助Oracle提供的完善的背景服務來完成這個恢複工作,而無需使用resetlogs,何樂而不為。