Saturday, December 13, 2014

RMAN restore 遇到 offline datafile 無法restore 的問題


某個使用9i資料庫且位於大陸深圳的客戶,在使用RMAN做異機還原的時候遇到類似以下的訊息,Offline 的datafile無法使用 RMAN 還原。

客戶是在 2011年 offline datafile的,所以也找不到當初的 archive log 來將這兩個datafile restore,也無法 recover datafile,也由於 resetlogs過了,所以事情變得非常麻煩,上 mos 查了一下資料,使用bbed解決。

由於 file$ 所記載的 datafile 資訊,datafile 不能斷號,如果 offline 的 file id 是最後一個! 那恭喜
,可以使用重建control file 的方式將最後一個 file id 狀況為 offline line 的 datafile 去掉,否則r就只能用 bbed 來騙資料庫。


狀況模擬與說明


以下為archive log mode 下模擬出來的情況。
1 . 新增 datafile 6個,file_id 11 ~ 16。
2 . offline 12 , 14 號 datafile ,並 recover 使其成為 offline,並多次 checkpoint 與 switch logfile。
3 . 使用 RMAN backup & restore ,並resetlogs。
4 . 使用RMAN 清除 archive log。
5 . 使用 RMAN backup & restore ,出現 RMAN-06023 no backup or copy of datafile n found to restore 狀況。

RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of restore command at 12/12/2014 08:47:23
RMAN-06026: some targets not found - aborting restore
RMAN-06023: no backup or copy of datafile 14 found to restore
RMAN-06023: no backup or copy of datafile 12 found to restore

select  a.ts#, a.file#, b.file_name, a.checkpoint_change#, a.last_change#, a.status
from  v$datafile a , dba_data_files b
where  a.file# = b.file_id
order by  a.file#
/




select  file#,   checkpoint_change#,     RESETLOGS_CHANGE#
from   v$datafile_header
/



可以看到 datafile_header 紀錄中, checkpoint_change# 與 resetlogs_change# 不一樣了。

要注意的是,datafile 有沒有被分配 extent

select count(*) from dba_extents where file_id in (12,14);
˙
查詢出來的沒有 row 就代表兩 datafile 是空的。



在已經沒有當初archive log 的備份且resetlogs狀態下,online 這兩個datafile 會遇到以下錯誤。

SQL> alter database datafile 12 online;
alter database datafile 12 online
*
ERROR at line 1:
ORA-01190: controlfile or data file 12 is from before the last RESETLOGS
ORA-01110: data file 12: '/u01/app/oracle/oradata/orcl/dbs1-02.dbf'


SQL>  alter database datafile 14 online;
 alter database datafile 14 online
*
ERROR at line 1:
ORA-01190: controlfile or data file 14 is from before the last RESETLOGS
ORA-01110: data file 14: '/u01/app/oracle/oradata/orcl/dbs1-04.dbf'


一個長期運作的資料庫,archive log 或 RMAN 很少有機會可以完整保留的,大部分都會有設定一個有效日期來刪除,所以目前看來應該沒救了,若要讓RMAN可以正常備份還原,看起來得使用非正規的手段恢復。

由於datafile沒內容物,當初客戶是因為 datafile 建錯名子,所以 offline 這兩個 datafile。

本次因客戶為需要,非得讓這樣的狀況正常,所以決定使用以下非正規的方法讓這兩個datafile正常運作。

BBED 工具準備與說明


9i BBED make : 9i 的 BBED要先 make 過後才能用

cd $ORACLE_HOME/rdbms/lib
make -f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed


BBED 可以使用 filelist,filelist中記錄 file id, file name , file size ,可以使用以下的sql指令的結果寫到 filelist中。

set pagesize 0
select file#||' '||name||' '||bytes from v$datafile ;

</u01/app/oracle/product/9.2.0/db_1/rdbms/lib> cat /tmp/filelist.lst
1 /u01/app/oracle/oradata/orcl/system01.dbf 429916160
2 /u01/app/oracle/oradata/orcl/undotbs01.dbf 414187520
3 /u01/app/oracle/oradata/orcl/cwmlite01.dbf 20971520
4 /u01/app/oracle/oradata/orcl/drsys01.dbf 20971520
5 /u01/app/oracle/oradata/orcl/example01.dbf 156631040
6 /u01/app/oracle/oradata/orcl/indx01.dbf 26214400
7 /u01/app/oracle/oradata/orcl/odm01.dbf 20971520
8 /u01/app/oracle/oradata/orcl/tools01.dbf 10485760
9 /u01/app/oracle/oradata/orcl/users01.dbf 26214400
10 /u01/app/oracle/oradata/orcl/xdb01.dbf 47185920
11 /u01/app/oracle/oradata/orcl/dbs1-01.dbf 104857600
12 /u01/app/oracle/oradata/orcl/dbs1-02.dbf 104857600
13 /u01/app/oracle/oradata/orcl/dbs1-03.dbf 104857600
14 /u01/app/oracle/oradata/orcl/dbs1-04.dbf 104857600
15 /u01/app/oracle/oradata/orcl/dbs1-05.dbf 104857600
16 /u01/app/oracle/oradata/orcl/dbs1-06.dbf 104857600


cd $ORACLE_HOME/rdbms/lib
$ ./bbed listfile=/tmp/filelist.lst blocksize=8192 mode=edit password=blockedit

觀察map一下利用 filelist.lst載入的資訊
BBED> info
 File#  Name                                                        Size(blks)
 -----  ----                                                        ----------
     1  /u01/app/oracle/oradata/orcl/system01.dbf                        52480
     2  /u01/app/oracle/oradata/orcl/undotbs01.dbf                       50560
     3  /u01/app/oracle/oradata/orcl/cwmlite01.dbf                        2560
     4  /u01/app/oracle/oradata/orcl/drsys01.dbf                          2560
     5  /u01/app/oracle/oradata/orcl/example01.dbf                       19120
     6  /u01/app/oracle/oradata/orcl/indx01.dbf                           3200
     7  /u01/app/oracle/oradata/orcl/odm01.dbf                            2560
     8  /u01/app/oracle/oradata/orcl/tools01.dbf                          1280
     9  /u01/app/oracle/oradata/orcl/users01.dbf                          3200
    10  /u01/app/oracle/oradata/orcl/xdb01.dbf                            5760
    11  /u01/app/oracle/oradata/orcl/dbs1-01.dbf                         12800
    12  /u01/app/oracle/oradata/orcl/dbs1-02.dbf                         12800
    13  /u01/app/oracle/oradata/orcl/dbs1-03.dbf                         12800
    14  /u01/app/oracle/oradata/orcl/dbs1-04.dbf                         12800
    15  /u01/app/oracle/oradata/orcl/dbs1-05.dbf                         12800
    16  /u01/app/oracle/oradata/orcl/dbs1-06.dbf                         12800


這次目的是要修改file id 為 12 , 14 的 file header,使這兩個 datafile 的 file header 中所記錄的 CHECKPOINT_CHANGE# ,RESETLOGS_CHANGE# 與其他datafile 一樣。

修改前建議做全資料庫備份,非常重要。

確認所需要的 offset 位置


切換 datafile
BBED> set filename '/u01/app/oracle/oradata/orcl/system01.dbf' block 1
        FILENAME        /u01/app/oracle/oradata/orcl/system01.dbf
        BLOCK#          1

確認目前使用的 datafile
BBED> map
 File: /u01/app/oracle/oradata/orcl/system01.dbf (0)
 Block: 1                                     Dba:0x00000000
------------------------------------------------------------
 Data File Header
 struct kcvfh, 360 bytes                    @0       
 ub4 tailchk                                @8188    

列出 block 1 各 struct 中的數值。
BBED> p kcvfh
.............................. 略 .............................. 
   ub4 kcvfhcrt                             @108      0x1f05276d
   ub4 kcvfhrlc                             @112      0x339fb560               -- resetlogs count
   struct kcvfhrls, 8 bytes                 @116     
      ub4 kscnbas                           @116      0x000571e1              -- resetlogs scn
      ub2 kscnwrp                           @120      0x0000
   ub4 kcvfhbti                             @124      0x00000000
   struct kcvfhbsc, 8 bytes                 @128     
      ub4 kscnbas                           @128      0x00000000
      ub2 kscnwrp                           @132      0x0000
   ub2 kcvfhbth                             @136      0x0000
   ub2 kcvfhsta                             @138      0x0004 (KCVFHOFZ)
   struct kcvfhckp, 36 bytes                @140     
      struct kcvcpscn, 8 bytes              @140     
         ub4 kscnbas                        @140      0x00057560                   -- checkpoint 低位
         ub2 kscnwrp                        @144      0x0000                          -- checkpoint 高位
      ub4 kcvcptim                          @148      0x33a0dc16                  -- checkpoint time
      ub2 kcvcpthr                          @152      0x0001
      union u, 12 bytes                     @156     
         struct kcvcprba, 12 bytes          @156     
            ub4 kcrbaseq                    @156      0x00000009
            ub4 kcrbabno                    @160      0x00000054
            ub2 kcrbabof                    @164      0x0010
         struct kcvcptr, 12 bytes           @156     
            struct kcrtrscn, 8 bytes        @156     
               ub4 kscnbas                  @156      0x00000009
               ub2 kscnwrp                  @160      0x0054
            ub4 kcrtrtim                    @164      0x00000010
      ub1 kcvcpetb[0]                       @168      0x02
      ub1 kcvcpetb[1]                       @169      0x00
      ub1 kcvcpetb[2]                       @170      0x00
      ub1 kcvcpetb[3]                       @171      0x00
      ub1 kcvcpetb[4]                       @172      0x00
      ub1 kcvcpetb[5]                       @173      0x00
      ub1 kcvcpetb[6]                       @174      0x00
      ub1 kcvcpetb[7]                       @175      0x00
   ub4 kcvfhcpc                             @176      0x00000041              -- checkpoint 計數
   ub4 kcvfhrts                             @180      0x339fb558
   ub4 kcvfhccc                             @184      0x00000040              -- checkpoint 計數 - 1
.............................. 略 .............................. 


說明
### 有關於 reset logs
kcvfhrlc  -- resetlogs count
struct kcvfhrls 裡面的 kscnbas -- resetlogs scn

### scn 相關
struct kcvfhrls 裡面的
kscnbas -- checkpoint 低位
kscnwrp -- checkpoint 高位
kcvcptim -- checkpoint time

kcvfhcpc -- checkpoint 計數
kcvfhccc -- checkpoint 計數 - 1

所以由上面列表,我們得知以下的 offset 是我們需要的

@112 
@116
@140
@144 
@148 
@176

由SYSTEM01中確定 6 個offset 位置中所需要的值。


可以使用 dump 卻確認 offset 中的數值 
dump /v dba fileid,block offset n

BBED>  dump /v  dba 1,1 offset 112 count 16
 File: /u01/app/oracle/oradata/orcl/system01.dbf (1)
 Block: 1       Offsets:  112 to  127  Dba:0x00400001
-------------------------------------------------------
 60b59f33 e1710500 00000000 00000000 l `?3嫭..........

 <16 bytes per line>

以上  60b59f33 就是 offset 112 內的數值,用以下的方式確認system01 block01裡面以下所需的 offset。


 @112 = 60b59f33
 @116 = e1710500

 @140 = 60750500
 @144 = 00000000    <= 觀察一下,不一定需要改。
 @148 = 16dca033
 @176 = 41000000
 @184 = 40000000

修改 file_id 12 , 14 中相關 offset 的值


BBED> set file 12 block 1
        FILE#           12
        BLOCK#          1

BBED> map
 File: /u01/app/oracle/oradata/orcl/dbs1-02.dbf (12)
 Block: 1                                     Dba:0x03000001
------------------------------------------------------------
 Data File Header

 struct kcvfh, 360 bytes                    @0       

 ub4 tailchk                                @8188    


BBED> modify /x 60b59f33 offset 112
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) Y
 File: /u01/app/oracle/oradata/orcl/dbs1-02.dbf (12)
 Block: 1                Offsets:  112 to  127           Dba:0x03000001
------------------------------------------------------------------------
 60b59f33 b46c0200 00000000 00000000 

 <32 bytes per line>

BBED>  modify /x e1710500 offset 116
 File: /u01/app/oracle/oradata/orcl/dbs1-02.dbf (12)
 Block: 1                Offsets:  116 to  131           Dba:0x03000001
------------------------------------------------------------------------
 e1710500 00000000 00000000 00000000 

 <32 bytes per line>

BBED> modify /x 60750500 offset 140
 File: /u01/app/oracle/oradata/orcl/dbs1-02.dbf (12)
 Block: 1                Offsets:  140 to  155           Dba:0x03000001
------------------------------------------------------------------------
 60750500 00000000 c6b39f33 01000000 

 <32 bytes per line>

BBED> modify /x 16dca033 offset 148
 File: /u01/app/oracle/oradata/orcl/dbs1-02.dbf (12)
 Block: 1                Offsets:  148 to  163           Dba:0x03000001
------------------------------------------------------------------------
 16dca033 01000000 12000000 02000000 

 <32 bytes per line>

BBED> modify /x 41000000 offset 176
 File: /u01/app/oracle/oradata/orcl/dbs1-02.dbf (12)
 Block: 1                Offsets:  176 to  191           Dba:0x03000001
------------------------------------------------------------------------
 41000000 20b59f33 09000000 00000000 

 <32 bytes per line>

BBED>  modify /x 40000000 offset 184
 File: /u01/app/oracle/oradata/orcl/dbs1-02.dbf (12)
 Block: 1                Offsets:  184 to  199           Dba:0x03000001
------------------------------------------------------------------------
 40000000 00000000 00000000 00000000 

 <32 bytes per line>


以相同的方式修改 dbs1-04.dbf,修改完成後記得 sum , sum apply 。

BBED> sum
Check value for File 12, Block 1:
current = 0xb21d, required = 0xd471

BBED> sum apply
Check value for File 12, Block 1:
current = 0xd471, required = 0xd471



DBVERIFY datafile 12 14的 block 1

BBED> verify dba 12,1
DBVERIFY - Verification starting
FILE = /u01/app/oracle/oradata/orcl/dbs1-02.dbf
BLOCK = 1

Total Blocks Examined         : 1
Total Blocks Processed (Data) : 0
Total Blocks Failing   (Data) : 0
Total Blocks Processed (Index): 0
Total Blocks Failing   (Index): 0
Total Blocks Empty            : 0
Total Blocks Marked Corrupt   : 0
Total Blocks Influx           : 0


BBED> verify dba 14,1
DBVERIFY - Verification starting
FILE = /u01/app/oracle/oradata/orcl/dbs1-04.dbf
BLOCK = 1

DBVERIFY - Verification complete

Total Blocks Examined         : 1
Total Blocks Processed (Data) : 0
Total Blocks Failing   (Data) : 0
Total Blocks Processed (Index): 0
Total Blocks Failing   (Index): 0
Total Blocks Empty            : 0
Total Blocks Marked Corrupt   : 0
Total Blocks Influx           : 0

修改 datafile header 後的操作


理論上應該可以 online datafile了。

SQL> alter database datafile 12 online;
alter database datafile 12 online
*
ERROR at line 1:
ORA-01113: file 12 needs media recovery
ORA-01110: data file 12: '/u01/app/oracle/oradata/orcl/dbs1-02.dbf'


SQL> recover datafile 12;
ORA-00283: recovery session canceled due to errors
ORA-00600: internal error code, arguments: [3672], [12], [4294967295], [64],
[4294967295], [], [], []

出現了錯誤,查為controlfile裡面紀錄的scn與修改過後的scn不一致,由於control file 還沒想到可以用任何工具修改,所以重建control file,把 datafile header中所記錄的寫回 controlfile。

SQL> col CHECKPOINT_CHANGE# HEADING 'CHECKPOINT|CHANGE#'
SQL> col RESETLOGS_CHANGE# HEADING 'RESETLOGS|CHANGE#'

SQL> select file#,   checkpoint_change#, RESETLOGS_CHANGE# 
   from v$datafile_header;

datafile_header 中紀錄的 scn ,resetlogs_change# 都一致。



SQL> select a.ts#, a.file#, b.file_name, a.checkpoint_change#, a.last_change#, a.status 
from v$datafile a , dba_data_files b 
where a.file# = b.file_id
order by a.file#
/
control file 中紀錄的 scn 不一樣,因此recover datafile 出現 ORA-00600: internal error code, arguments: [3672] 錯誤


重建 controlfile 即可將 datafile 12 , 14 正常 online。

CREATE CONTROLFILE REUSE DATABASE "ORCL" NORESETLOGS  ARCHIVELOG
    MAXLOGFILES 50
    MAXLOGMEMBERS 5
    MAXDATAFILES 100
    MAXINSTANCES 1
    MAXLOGHISTORY 226
LOGFILE
  GROUP 1 '/u01/app/oracle/oradata/orcl/redo01.log'  SIZE 100M,
  GROUP 2 '/u01/app/oracle/oradata/orcl/redo02.log'  SIZE 100M,
  GROUP 3 '/u01/app/oracle/oradata/orcl/redo03.log'  SIZE 100M
DATAFILE
  '/u01/app/oracle/oradata/orcl/system01.dbf',
  '/u01/app/oracle/oradata/orcl/undotbs01.dbf',
  '/u01/app/oracle/oradata/orcl/cwmlite01.dbf',
  '/u01/app/oracle/oradata/orcl/drsys01.dbf',
  '/u01/app/oracle/oradata/orcl/example01.dbf',
  '/u01/app/oracle/oradata/orcl/indx01.dbf',
  '/u01/app/oracle/oradata/orcl/odm01.dbf',
  '/u01/app/oracle/oradata/orcl/tools01.dbf',
  '/u01/app/oracle/oradata/orcl/users01.dbf',
  '/u01/app/oracle/oradata/orcl/xdb01.dbf',
  '/u01/app/oracle/oradata/orcl/dbs1-01.dbf',
  '/u01/app/oracle/oradata/orcl/dbs1-02.dbf',
  '/u01/app/oracle/oradata/orcl/dbs1-03.dbf',
  '/u01/app/oracle/oradata/orcl/dbs1-04.dbf',
  '/u01/app/oracle/oradata/orcl/dbs1-05.dbf',
  '/u01/app/oracle/oradata/orcl/dbs1-06.dbf'
CHARACTER SET AL32UTF8
;

# Take files offline to match current control file.
ALTER DATABASE DATAFILE '/u01/app/oracle/oradata/orcl/dbs1-02.dbf' OFFLINE DROP; 
ALTER DATABASE DATAFILE '/u01/app/oracle/oradata/orcl/dbs1-04.dbf' OFFLINE DROP; 

# Recovery is required if any of the datafiles are restored backups,
# or if the last shutdown was not normal or immediate.
RECOVER DATABASE

# All logs need archiving and a log switch is needed.
ALTER SYSTEM ARCHIVE LOG ALL;

# Database can now be opened normally.
ALTER DATABASE OPEN;


再重新把 datafile online 即可

No comments:

Post a Comment