基於RMAN實現壞塊介質恢復(blockrecover)

us_yunleiwang發表於2013-12-05

對於物理損壞的資料塊,我們可以透過RMAN塊介質恢復(BLOCK MEDIA RECOVERY)功能來完成受損塊的恢復,而不需要恢復整個資料庫或所有檔案來修復這些少量受損的資料塊。恢復整個資料庫或資料檔案那不是大炮用來打蚊子,有點不值得!但前提條件是你得有一個可用的RMAN備份存在,因此,無論何時備份就是一切。本文演示了產生壞塊即使用RMAN實現壞塊恢復的全過程。

 

1、建立演示環境

  1. SQL> select * from v$version where rownum<2;  
  2.   
  3. BANNER  
  4. --------------------------------------------------------------------------------  
  5. Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production  
  6.   
  7. --建立用於演示的data file  
  8. SQL> create tablespace tbs_tmp datafile '/u02/database/usbo/oradata/tbs_tmp.dbf' size 10m autoextend on;  
  9.   
  10. SQL> conn scott/tiger;  
  11.   
  12. --基於新的資料檔案建立物件tb_tmp  
  13. SQL> create table tb_tmp tablespace tbs_tmp as select * from dba_objects;  
  14.   
  15. SQL> col file_name format a60  
  16. SQL> select file_id,file_name from dba_data_files where tablespace_name='TBS_TMP';  
  17.   
  18.    FILE_ID FILE_NAME  
  19. ---------- ------------------------------------------------------------  
  20.          6 /u02/database/usbo/oradata/tbs_tmp.dbf  
  21.   
  22. --表物件tb_tmp上的資訊,包含對應的檔案資訊,頭部塊,總塊數  
  23. SQL> select segment_name , header_file , header_block,blocks        
  24.   2  from dba_segments  
  25.   3  where segment_name = 'TB_TMP' and owner='SCOTT';  
  26.   
  27. SEGMENT_NAME                   HEADER_FILE HEADER_BLOCK     BLOCKS  
  28. ------------------------------ ----------- ------------ ----------  
  29. TB_TMP                                   6          130       1152  
  30.   
  31. --首先使用rman備份對應的資料檔案  
  32. $ $ORACLE_HOME/bin/rman target /  
  33. RMAN> backup datafile 6 tag=health;  
  34.   
  35. Starting backup at 2013/08/28 17:03:15  
  36. allocated channel: ORA_DISK_1  
  37. channel ORA_DISK_1: SID=24 device type=DISK  
  38. channel ORA_DISK_1: starting full datafile backup set  
  39. channel ORA_DISK_1: specifying datafile(s) in backup set  
  40. input datafile file number=00006 name=/u02/database/usbo/oradata/tbs_tmp.dbf  
  41. channel ORA_DISK_1: starting piece 1 at 2013/08/28 17:03:16  
  42. channel ORA_DISK_1: finished piece 1 at 2013/08/28 17:03:17  
  43. piece handle=/u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp tag=HEALTH comment=NONE  
  44. channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01  
  45. Finished backup at 2013/08/28 17:03:17  
  46. RMAN> exit  

2、單塊資料塊損壞的恢復處理

  1. --下面使用了linux自帶的dd命令來損壞單塊資料塊  
  2. [oracle@linux1 ~]$ dd of=/u02/database/usbo/oradata/tbs_tmp.dbf bs=8192 conv=notrunc seek=130 <
  3. > Corrupted block!  
  4. > EOF  
  5. 0+1 records in  
  6. 0+1 records out  
  7. 17 bytes (17 B) copied, 0.000184519 seconds, 92.1 kB/s  
  8.   
  9. --清空buffer cache  
  10. SQL> alter system flush buffer_cache;  
  11.   
  12. --查詢表對相 tb_tmp,收到ORA-01578  
  13. SQL> select count(*) from tb_tmp;  
  14. select count(*) from tb_tmp  
  15. *  
  16. ERROR at line 1:  
  17. ORA-01578: ORACLE data block corrupted (file # 6, block # 130)  
  18. ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'  
  19.   
  20. --查詢檢視v$database_block_corruption,提示有壞塊,注意該檢視可能不會返回任何資料,如無返回,先執行backup validate  
  21. SQL> select * from v$database_block_corruption;  
  22.   
  23.      FILE#     BLOCK#     BLOCKS CORRUPTION_CHANGE# CORRUPTIO  
  24. ---------- ---------- ---------- ------------------ ---------  
  25.          6        129          1                  0 CORRUPT  
  26.   
  27. --也可以使用dbv工具來校驗壞塊,參考: http://blog.csdn.net/robinson_0612/article/details/6530890     
  28.   
  29. --下面使用blockrecover來恢復壞塊        
  30. RMAN> blockrecover datafile 6 block 130;  
  31.   
  32. Starting recover at 2013/08/28 17:22:25  
  33. using target database control file instead of recovery catalog  
  34. allocated channel: ORA_DISK_1  
  35. channel ORA_DISK_1: SID=24 device type=DISK  
  36.   
  37. channel ORA_DISK_1: restoring block(s)  
  38. channel ORA_DISK_1: specifying block(s) to restore from backup set  
  39. restoring blocks of datafile 00006  
  40. channel ORA_DISK_1: reading from backup piece /u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp  
  41. channel ORA_DISK_1: piece handle=/u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp tag=HEALTH  
  42. channel ORA_DISK_1: restored block(s) from backup piece 1  
  43. channel ORA_DISK_1: block restore complete, elapsed time: 00:00:01  
  44.   
  45. starting media recovery  
  46. media recovery complete, elapsed time: 00:00:03  
  47.   
  48. Finished recover at 2013/08/28 17:22:31  
  49.   
  50. --再次查詢表tb_emp正常  
  51. SQL> select count(*) from tb_tmp;  
  52.   
  53.   COUNT(*)  
  54. ----------  
  55.      72449  

3、多塊資料塊損壞的恢復處理

  1. --下面使用linux dd命令對不連續塊損壞  
  2. [oracle@linux1 ~]$ dd of=/u02/database/usbo/oradata/tbs_tmp.dbf bs=8192 conv=notrunc seek=133 <
  3. > New corrupted block!  
  4. > EOF  
  5. 0+1 records in  
  6. 0+1 records out  
  7. 21 bytes (21 B) copied, 0.000182835 seconds, 115 kB/s  
  8. [oracle@linux1 ~]$ dd of=/u02/database/usbo/oradata/tbs_tmp.dbf bs=8192 conv=notrunc seek=143 <
  9. > New corrupted block!  
  10. > EOF  
  11. 0+1 records in  
  12. 0+1 records out  
  13. 21 bytes (21 B) copied, 0.000115527 seconds, 182 kB/s  
  14. [oracle@linux1 ~]$ dd of=/u02/database/usbo/oradata/tbs_tmp.dbf bs=8192 conv=notrunc seek=153 <
  15. > New corrupted block!  
  16. > EOF  
  17. 0+1 records in  
  18. 0+1 records out  
  19. 21 bytes (21 B) copied, 0.000335781 seconds, 62.5 kB/s  
  20.   
  21. SQL> alter system flush buffer_cache;  
  22.   
  23. --下面提示塊133被損壞,注意我們損壞了多塊資料塊,但查詢時,從塊號最小的開始提示,如133被修復後還有壞塊則繼續提示133之後的壞塊  
  24. SQL> select count(*) from scott.tb_tmp;  
  25. select count(*) from scott.tb_tmp  
  26. *  
  27. ERROR at line 1:  
  28. ORA-01578: ORACLE data block corrupted (file # 6, block # 133)  
  29. ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'  
  30.   
  31. --查詢檢視v$database_block_corruption無任何記錄  
  32. SQL> select * from v$database_block_corruption;  
  33.   
  34. no rows selected  
  35.   
  36. --下面使用backup validate來校驗資料檔案  
  37. RMAN> backup validate datafile 6;  
  38.   
  39. Starting backup at 2013/08/29 09:42:04  
  40. using target database control file instead of recovery catalog  
  41. allocated channel: ORA_DISK_1  
  42. channel ORA_DISK_1: SID=22 device type=DISK  
  43. channel ORA_DISK_1: starting full datafile backup set  
  44. channel ORA_DISK_1: specifying datafile(s) in backup set  
  45. input datafile file number=00006 name=/u02/database/usbo/oradata/tbs_tmp.dbf  
  46. channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01  
  47. List of Datafiles  
  48. =================  
  49. File Status Marked Corrupt Empty Blocks Blocks Examined High SCN  
  50. ---- ------ -------------- ------------ --------------- ----------  
  51. 6    FAILED 0              223          1408            838489       --欄位Status為FAILED  
  52.   File Name: /u02/database/usbo/oradata/tbs_tmp.dbf  
  53.   Block Type Blocks Failing Blocks Processed  
  54.   ---------- -------------- ----------------  
  55.   Data       0              1029              
  56.   Index      0              0                 
  57.   Other      3              156             --有3個Blocks Failing  
  58.   
  59. validate found one or more corrupt blocks  
  60. See trace file /u02/database/usbo/diag/rdbms/usbo/usbo/trace/usbo_ora_27874.trc for details  
  61. Finished backup at 2013/08/29 09:42:06  
  62.   
  63. --再次查詢v$database_block_corruption,表明有3個損壞的塊  
  64. SQL> select * from v$database_block_corruption;  
  65.   
  66.      FILE#     BLOCK#     BLOCKS CORRUPTION_CHANGE# CORRUPTIO  
  67. ---------- ---------- ---------- ------------------ ---------  
  68.          6        153          1                  0 CORRUPT  
  69.          6        143          1                  0 CORRUPT  
  70.          6        133          1                  0 CORRUPT  
  71.   
  72. --下面直接使用blockrecover corruption list來恢復,如下所有剛剛被校驗的壞塊都會被恢復  
  73. RMAN> blockrecover corruption list;    
  74.   
  75. Starting recover at 2013/08/29 10:05:24  
  76. using channel ORA_DISK_1  
  77.   
  78. channel ORA_DISK_1: restoring block(s)  
  79. channel ORA_DISK_1: specifying block(s) to restore from backup set  
  80. restoring blocks of datafile 00006  
  81. channel ORA_DISK_1: reading from backup piece /u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp  
  82. channel ORA_DISK_1: piece handle=/u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp tag=HEALTH  
  83. channel ORA_DISK_1: restored block(s) from backup piece 1  
  84. channel ORA_DISK_1: block restore complete, elapsed time: 00:00:01  
  85.   
  86. starting media recovery  
  87. media recovery complete, elapsed time: 00:00:03  
  88.   
  89. Finished recover at 2013/08/29 10:05:28  
  90.   
  91. --校驗結果  
  92. SQL> select count(*) from scott.tb_tmp;  
  93.   
  94.   COUNT(*)  
  95. ----------  
  96.      72449  

4、壞塊的物件定位與影響

  1. --下面我們查詢塊號為163上的物件  
  2. SQL> select dbms_rowid.rowid_object(rowid) object_id,dbms_rowid.rowid_relative_fno(rowid) file_id,  
  3.   2  dbms_rowid.rowid_block_number(rowid) block_id,owner,object_name,object_id  
  4.   3  from scott.tb_tmp where dbms_rowid.rowid_block_number(rowid)=163 and rownum<=2;  
  5.   
  6.  OBJECT_ID    FILE_ID   BLOCK_ID OWNER        OBJECT_NAME                     OBJECT_ID  
  7. ---------- ---------- ---------- ------------ ------------------------------ ----------  
  8.      74555          6        163 SYS          GV_$QUEUEING_MTH                     2439  
  9.      74555          6        163 PUBLIC       GV$QUEUEING_MTH                      2440  
  10.   
  11. --使用上面的方法,我們損塊塊163,173,此處不再列出  
  12.   
  13. a、對於壞塊物件無法進行聚合彙總等操作       
  14. SQL> select count(*) from scott.tb_tmp;  
  15. select count(*) from scott.tb_tmp  
  16. *  
  17. ERROR at line 1:  
  18. ORA-01578: ORACLE data block corrupted (file # 6, block # 163)  
  19. ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'  
  20.   
  21. b、對於壞塊上的記錄無法被查詢  
  22. --我們使用基於之前查詢到的OBJECT_ID來查詢  
  23. SQL> select owner,object_name,object_id from scott.tb_tmp where object_id in(2439,2440);  
  24. select owner,object_name,object_id from scott.tb_tmp where object_id in(2439,2440)  
  25.                                               *  
  26. ERROR at line 1:  
  27. ORA-01578: ORACLE data block corrupted (file # 6, block # 163)  
  28. ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'  
  29.   
  30. --如下面的查詢,位於損壞塊上的資料無法被查詢到,但對於未損壞的依舊可以查詢。下面的查詢時塊161上的物件  
  31. SQL> select owner,object_name,object_id from scott.tb_tmp   
  32.   2  where dbms_rowid.rowid_block_number(rowid)=161 and rownum<3;  
  33.   
  34. OWNER                          OBJECT_NAME                     OBJECT_ID  
  35. ------------------------------ ------------------------------ ----------  
  36. PUBLIC                         GV$RECOVERY_LOG                      2285  
  37. SYS                            GV_$ARCHIVE_GAP                      2286  
  38.   
  39. --Author : Robinson Cheng  
  40. --Blog   : http://blog.csdn.net/robinson_0612  
  41.        
  42. c、定位受損塊所對應的物件  
  43. SQL> run get_obj_name_from_corrupt_block  
  44.   1  SELECT tablespace_name,  
  45.   2         segment_type,  
  46.   3         owner,  
  47.   4         segment_name,  
  48.   5         partition_name  
  49.   6    FROM dba_extents  
  50.   7*  WHERE file_id = &file_id AND &block_id BETWEEN block_id AND block_id + blocks - 1  
  51. Enter value for file_id: 6  
  52. Enter value for block_id: 133  
  53. old   7:  WHERE file_id = &file_id AND &block_id BETWEEN block_id AND block_id + blocks - 1  
  54. new   7:  WHERE file_id = 6 AND 133 BETWEEN block_id AND block_id + blocks - 1  
  55.   
  56. TABLESPACE_NAME                SEGMENT_TYPE       OWNER          SEGMENT_NAME      PARTITION_NAME  
  57. ------------------------------ ------------------ -------------- ----------------- -----------------  
  58. TBS_TMP                        TABLE              SCOTT          TB_TMP   
  59.   
  60. d、對於損壞的資料檔案,預設情況下,不能對其進行備份,如下  
  61. RMAN> backup datafile 6 tag='corruption';                                                      
  62.                                                                                                         
  63. Starting backup at 2013/08/29 10:37:32                                                         
  64. using channel ORA_DISK_1                                                                       
  65. channel ORA_DISK_1: starting full datafile backup set                                          
  66. channel ORA_DISK_1: specifying datafile(s) in backup set                                       
  67. input datafile file number=00006 name=/u02/database/usbo/oradata/tbs_tmp.dbf                   
  68. channel ORA_DISK_1: starting piece 1 at 2013/08/29 10:37:32                                    
  69. RMAN-00571: ===========================================================                        
  70. RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============                        
  71. RMAN-00571: ===========================================================                        
  72. RMAN-03009: failure of backup command on ORA_DISK_1 channel at 08/29/2013 10:37:33             
  73. ORA-19566: exceeded limit of 0 corrupt blocks for file /u02/database/usbo/oradata/tbs_tmp.dbf   
  74.   
  75. --需要設定允許損壞塊的數量之後才能進行備份  
  76. RMAN> run{  
  77. 2> set maxcorrupt for datafile 6 to 2;  
  78. 3> backup datafile 6 tag='corruption';  
  79. 4> }  
  80.   
  81. executing command: SET MAX CORRUPT  
  82.   
  83. Starting backup at 2013/08/29 10:41:24  
  84. using channel ORA_DISK_1  
  85. channel ORA_DISK_1: starting full datafile backup set  
  86. channel ORA_DISK_1: specifying datafile(s) in backup set  
  87. input datafile file number=00006 name=/u02/database/usbo/oradata/tbs_tmp.dbf  
  88. channel ORA_DISK_1: starting piece 1 at 2013/08/29 10:41:25  
  89. channel ORA_DISK_1: finished piece 1 at 2013/08/29 10:41:26  
  90. piece handle=/u02/database/usbo/fr_area/USBO/backupset/2013_08_29/o1_mf_nnndf_CORRUPTION_91xf6o18_.bkp tag=CORRUPTION comment=NONE  
  91. channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01  
  92. Finished backup at 2013/08/29 10:41:26         
  93.   
  94. --檢視備份資訊如下,應在修復壞塊後重新備份以避免由於保留策略導致先前可用的備份被aged out  
  95. RMAN> list backup summary;  
  96.   
  97. List of Backups  
  98. ===============  
  99. Key     TY LV S Device Type Completion Time     #Pieces #Copies Compressed Tag  
  100. ------- -- -- - ----------- ------------------- ------- ------- ---------- ---  
  101. 1       B  F  A DISK        2013/08/28 17:03:17 1       1       NO         HEALTH  
  102. 3       B  F  A DISK        2013/08/29 10:41:25 1       1       NO         CORRUPTION  

5、後記
a、對於受損的資料塊,僅僅壞塊上的資料無法被查詢或讀取,其餘正常塊的資料依舊可以使用。
b、對於受損的表物件進行聚合等相關運算時收到錯誤提示,因為壞塊上的資料無法被統計。如果你聚合的是索引列,索引未損壞的情形則可正常返回。
c、可以基於RMAN可用的備份檔案實現塊介質恢復,其資料檔案無需offline,開銷最小,影響最小。
d、對於多個資料塊的損壞,先執行backup validate校驗資料庫或相應的資料檔案以便標記受損的壞塊後,填充v$database_block_corruption以及後續恢復。
e、對於使用backup validate 校驗後的情形,壞塊恢復時可以直接使用blockrecover corruption list一次性恢復所有的壞塊。
f、預設情況下,存在壞塊的資料檔案無法成功備份,也會導致自動備份指令碼失敗。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23490154/viewspace-1062376/,如需轉載,請註明出處,否則將追究法律責任。

相關文章