模擬壞塊故障並搶救資料(一.普通表)

hooca發表於2015-05-02
OS:Oracle Linux 5u8
DB:Oracle 11.2.0.4.0

已建立示例表空間CCDATA,schema為cc,資料檔案o1_mf_ccdata_bn8l5x7l_.dbf

找到該表空間中的一個表CUSTACCOUNTS,看看它的block_id範圍


點選(此處)摺疊或開啟

  1. select owner, segment_name, segment_type,
  2. extent_id, file_id, block_id, blocks
  3. from dba_extents
  4. where owner='CC' and segment_name='CUSTACCOUNTS'

OWNER SEGMENT_NAME SEGMENT_TYPE EXTENT_ID FILE_ID BLOCK_ID BLOCKS
CC CUSTACCOUNTS TABLE 0 5 896 128
CC CUSTACCOUNTS TABLE 1 5 1152 128
CC CUSTACCOUNTS TABLE 2 5 1408 128
CC CUSTACCOUNTS TABLE 3 5 1664 128
CC CUSTACCOUNTS TABLE 4 5 1792 128
CC CUSTACCOUNTS TABLE 5 5 2048 128
CC CUSTACCOUNTS TABLE 6 5 2304 128
CC CUSTACCOUNTS TABLE 7 5 2560 128
CC CUSTACCOUNTS TABLE 8 5 2688 128
CC CUSTACCOUNTS TABLE 9 5 2944 128
CC CUSTACCOUNTS TABLE 10 5 3200 128
CC CUSTACCOUNTS TABLE 11 5 3456 128
CC CUSTACCOUNTS TABLE 12 5 3712 128
這裡我們修改block_id為1000的塊,剛好落在這個表裡面。

使用UE開啟資料檔案。怎麼確定block_id=1000在資料檔案的哪個位置呢。塊大小8192位元組,8192×1000=8192,000,轉換成16進製為007D 0000。隨意改這一行第一個數字為FF,儲存退出。


注:以上操作要在Oracle關閉狀態下操作,別且要做好備份。

開啟資料庫,試試查詢該表。

點選(此處)摺疊或開啟

  1. SQL> select * from CUSTACCOUNTS;


      CAID CAVALIDFROM         CAVALIDTO
---------- ------------------- -------------------
CANAME
----------------------------------------------------------------
CAPIN
----------------------------------------------------------------
CALASTLOGIN         CAFAILEDLOGINS CALASTFAILEDLOGIN
------------------- -------------- -------------------
     10763 1970-01-01 00:00:00 4312-12-31 23:59:59
0000000000010763
1234
1970-01-01 00:00:00              0 1970-01-01 00:00:00
--查詢進行了一段時間後,報錯
ERROR:
ORA-01578: ORACLE data block corrupted (file # 5, block # 1000)
ORA-01110: data file 5: '/oradata/APR/datafile/o1_mf_ccdata_bn8l5x7l_.dbf'

仔細看會發現,壞塊block_id為1000,正好是我們改掉的塊。

這時,如果有RMAN備份,恢復很簡單

點選(此處)摺疊或開啟

  1. RMAN> blockrecover datafile 5 block 1000;
這裡我們假設沒有RMAN備份,儘可能多的搶救資料。
壞塊檢查

當前已出現的壞塊記錄在檢視v$database_block_corruption

點選(此處)摺疊或開啟

  1. select * from v$database_block_corruption

     FILE#     BLOCK#     BLOCKS CORRUPTION_CHANGE# CORRUPTION_TYPE
---------- ---------- ---------- ------------------ ------------------
         5       1000          1                  0 CORRUPT

另外,可以使用DBV命令線上檢查資料檔案的壞塊

點選(此處)摺疊或開啟

  1. [oracle@apr datafile]$ dbv file=o1_mf_ccdata_bn8l5x7l_.dbf

  2. DBVERIFY: Release 11.2.0.4.0 - Production on Sat May 2 16:54:32 2015

  3. Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.

  4. DBVERIFY - Verification starting : FILE = /oradata/APR/datafile/o1_mf_ccdata_bn8l5x7l_.dbf
  5. Page 10000 is marked corrupt
  6. Corrupt block relative dba: 0x01402710 (file 5, block 10000)
  7. Bad header found during dbv:
  8. Data in bad block:
  9.  type: 255 format: 2 rdba: 0x01402710
  10.  last change scn: 0x0000.0011261f seq: 0x1 flg: 0x06
  11.  spare1: 0x0 spare2: 0x0 spare3: 0x0
  12.  consistency value in tail: 0x261f0601
  13.  check value in block header: 0x7764
  14.  computed block checksum: 0xf9



  15. DBVERIFY - Verification complete

  16. Total Pages Examined : 222848
  17. Total Pages Processed (Data) : 103647
  18. Total Pages Failing (Data) : 0
  19. Total Pages Processed (Index): 54090
  20. Total Pages Failing (Index): 0
  21. Total Pages Processed (Other): 2756
  22. Total Pages Processed (Seg) : 0
  23. Total Pages Failing (Seg) : 0
  24. Total Pages Empty : 62354
  25. Total Pages Marked Corrupt : 1
  26. Total Pages Influx : 0
  27. Total Pages Encrypted : 0
  28. Highest block SCN : 1135578 (0.1135578)


根據羅敏的《感悟Oracle核心技術》,推薦用ROWID掃描方法搶救資料。

//2016.04.08更新
首先需要定位到壞塊屬於哪個資料庫物件。

點選(此處)摺疊或開啟

  1. select owner,segment_name,segment_type,block_id,blocks from dba_extents
    where file_id = 5
    and block_id  10000;
最小ROW_ID
SELECT dbms_rowid.rowid_create(1, , , , 0) LOW_RID from DUAL;
最大ROW_ID
SELECT dbms_rowid.rowid_create(1, , , +1, 0) HI_RID from DUAL;

點選(此處)摺疊或開啟

  1. SQL> SELECT OBJECT_ID FROM DBA_OBJECTS WHERE OWNER='CC' AND OBJECT_NAME='CUSTACCOUNTS';


 OBJECT_ID
----------
     87524


點選(此處)摺疊或開啟

  1. SQL> SELECT dbms_rowid.rowid_create(1, 87524, 5, 1000, 0) LOW_RID from DUAL;
  2. LOW_RID
    ------------------------------------
    AAAVXkAAFAAAAPoAAA
  3. SQL> SELECT dbms_rowid.rowid_create(1, 87524, 5, 1001, 0) HI_RID from DUAL;
  4. HI_RID
    ------------------------------------
    AAAVXkAAFAAAAPpAAA

點選(此處)摺疊或開啟

  1. --將壞塊所在的錶轉存到另一“安全”的表空間
  2. CREATE TABLE ccbak.CUSTACCOUNTS_BAK
  3. TABLESPACE ccbak
  4. AS SELECT /*+ ROWID(A) */ * FROM CC.CUSTACCOUNTS A
  5. WHERE ROWID < 'AAAVXkAAFAAAAPoAAA';
  6. --繼續
  7. INSERT INTO ccbak.CUSTACCOUNTS_BAK 
  8. SELECT /*+ ROWID(A) */ * FROM CC.CUSTACCOUNTS A
  9. WHERE ROWID >= 'AAAVXkAAFAAAAPpAAA';
  10. commit;
將問題表刪除,並清空回收站,但壞塊並不會消失,最好將整個資料檔案所關聯的表空間匯出,再重新匯入。

點選(此處)摺疊或開啟

  1. drop table CC.CUSTACCOUNTS;
  2. purge recyclebin;
匯出表空間,這裡的schemas CC就是表空間的全部。

點選(此處)摺疊或開啟

  1. SQL> create directory ccdir as '/home/oracle/ccdir';
  2. [oracle@apr ~]$ expdp system/oracle@apr schemas=cc dumpfile=cc.dmp DIRECTORY=ccdir
再刪除整個表空間

點選(此處)摺疊或開啟

  1. SQL> drop tablespace ccdata including contents AND datafiles;
重建表空間,並指定其為使用者的預設表空間

點選(此處)摺疊或開啟

  1. SQL> create tablespace ccdata datafile size 1G autoextend on;

  2. SQL> alter user cc default tablespace ccdata;
匯入schemas

點選(此處)摺疊或開啟

  1. impdp system/oracle@apr DIRECTORY=ccdir DUMPFILE=cc.dmp SCHEMAS=cc
重新用DBV檢查,確認已經沒有壞塊了。

注:ROWID掃描方法適用於使用者表和分割槽表段內的壞塊,對段頭和系統表壞塊不適用。

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

相關文章