Oracle壞塊處理

llnnmc發表於2018-05-06

有時Oracle資料檔案的損壞只是一小部分塊:檔案仍可用,但特定塊被損壞。這種情況下,檔案將保持聯機,終端使用者可能不知道存在的問題,直到讀取到壞塊時才會發現。如果一個會話命中一個壞塊,它將返回錯誤給使用者程式,同時將一條訊息寫入警報日誌。

 

一、壞塊的檢測

 

1、警告日誌可以看到壞塊

 

ORA-01578:壞塊錯誤

 

2、透過兩個初始化引數實時監測壞塊

 

db_block_checking:預設false,塊內資料的邏輯一致性檢查,效能負荷較大

show parameter db_block_checking;

true:讀寫時都檢查

flase:除system表空間塊外不檢查

low:改變的資料

medium:檢查索引組織表

full:全部檢查

 

db_block_checksum:預設typical,檢查記憶體和硬碟塊資料是否一致,效能負荷不大

show parameter db_block_checksum;

typicaltrue):DBWn寫盤時會計算一個稱為檢驗和checksum的值,儲存在block的頭部。讀取該塊時將校驗checksum值。

full:除typical外,在update/delete前校驗checksum,並在變化後重新計算checksum,另會計算記憶體中的塊損壞並阻止寫入磁碟。

offfalse):正常情況下,Oracle會對每個日誌的block計算checksum,如果設為off,則只計算system表空間的checksum

 

3、RMAN檢測壞塊

 

RMAN在執行備份操作時會自動檢測壞塊,預設當命中壞塊時立即終止備份操作。如果需要,可設定對壞塊容錯度的RMAN備份,則在備份過程中命中壞塊時將繼續備份,但會在其儲存庫中記錄發現的壞塊。以下示例將壞塊容錯度設為10,只要遇到的壞塊不超過10個,備份將繼續進行

RMAN> run {

set maxcorrupt for datafile 7 to 10;

backup datafile 7;

}

 

在正常執行中,將不使用set maxcorrupt關鍵字,遇到壞塊時,備份將失敗,使用者立即知道錯誤。然後用set maxcorrupt再次執行備份,完成後可查詢以下幾個檢視確定塊損壞範圍

v$database_block_corruption:記錄壞塊所在的位置,包括資料檔案號和塊編號等資訊。

v$backup_corruption:針對備份集備份遇到的壞塊統計。

v$copy_corruption:針對映像副本備份遇到的壞塊統計。

 

預設情況下,RMAN總是檢查物理損壞,也就是非RMAN中的介質損壞。也可讓RMAN檢查邏輯損壞,即軟體損壞。要改寫備份的預設值,可使用nochecksumcheck logical關鍵字。

 

不檢查資料檔案物理損壞的備份

RMAN> backup nochecksum datafile 4;

 

檢查資料檔案邏輯損壞(包括物理損壞)的備份

RMAN> backup check logical datafile 4;

 

若使用validate關鍵字,則可在要進行的備份物件上執行塊損壞檢查,但不會執行實際的備份操作。

 

檢查資料檔案的物理損壞

RMAN> backup validate datafile 4;

 

檢查資料檔案物理損壞和邏輯損壞

RMAN> backup validate check logical datafile 4;

 

4、dbverify工具檢測壞塊

 

針對資料檔案檢查壞塊,無論檔案聯機或離線,資料庫開啟或關閉都可以,預設塊大小8192

dbv file=/home/oracle/app/oracle/oradata/mes/cmes01.dbf [blocksize=...]

 

5、其它工具檢查

 

備份工具expexpdp在做資料匯出時會檢查是否存在壞塊,遭遇壞塊時匯出會終止,並提示ORA-01578錯誤。如果損壞的塊是索引,通常可以透過重建索引來解決。如果損壞的塊是資料,可以透過設定如下內部事件使exp操作跳過壞塊

alter system set events='10231 trace name context forever,level 10';

 

之後重新執行匯出命令,匯出相關的表,然後執行drop table命令將表刪除,再重建表並匯入資料。

 

禁用壞塊跳過

alter system set events='10231 trace name context off';

 

analyze命令也會對錶和索引的物理儲存執行檢查,該指令更新表或索引的後設資料,同時也可以進行壞塊的檢查,但不會將已損壞的塊標記為corrupt,檢測結果輸出在user_dump_dest目錄下的使用者trace檔案中。如:

analyze table tablename validate structure cascade;

analyze index indexname validate structure;

 

Oracle提供的PL/SQL程式包dbms_repair也可以檢查和處理表和索引中出現的壞塊問題,包括標記和跳過壞塊。

 

二、RMAN塊介質恢復

 

塊介質恢復(BMRBlock Media Recovery)將還原和恢復操作的粒度從資料檔案改為塊。與檔案還原和恢復相比,檔案不必離線,正常DML可以繼續,恢復的時間也大大減少,因為操作只涉及到受損的塊,而不是整個檔案。

 

BMR機制給RMAN提供一個需要恢復的一個或多個塊的列表。RMAN將從備份集或映像副本中提取這些塊的備份並寫入資料檔案。然後,RMAN將遍歷自備份後生成的歸檔日誌,提取與還原塊相關的重做記錄並應用它們。恢復將是完整的,邏輯上不可能執行不完整恢復,只對一個塊進行不完整恢復將使資料庫處於不一致的狀態。如果使用者會話在BMR過程完成之前命中到壞塊,將仍會接收到ORA-01578的壞塊錯誤,但也可能BMR操作將在使用者發現問題前完成。

 

RMAN使用blockrecover命令來進行塊介質恢復。以下命令將指定要還原和恢復的一個或多個塊的列表

RMAN> blockrecover datafile 7 block 5;

 

可以同時指定多個資料檔案和多個塊

RMAN> blockrecover datafile 7 block 5, 6, 7 datafile 9 block 21, 25;

 

可能會有對備份本身完整性的懷疑,那麼可明確指示RMAN從已知是好的備份中還原和恢復塊。如指定要提取的備份集編號,或者指定TAG標記

RMAN> blockrecover datafile 7 block 5 from backupset 12;

RMAN> blockrecover datafile 7 block 5 from tag TAG20151114T173349;

 

如果損壞範圍較大,BMR的另外兩個選項可簡化此過程:

其一,假定已在RMAN備份過程中透過設定maxcorrupt最大壞塊數量填充了檢視v$database_block_corruption,那麼使用corruption list選項將指示RMAN還原和恢復檢視中的每一個塊

RMAN> blockrecover corruption list;

其二,使用until選項可指定要還原的備份來自於發生損壞前的一個時間點。如以下將指示RMAN從至少一週前的備份中還原和恢復在前一次備份時發現的每個壞塊

RMAN> blockrecover corruption list until time sysdate - 7;

 

另外還有透過指定損壞資料塊的DBAdata block address)來恢復

blockrecover tablespace blocktbs dba 41943172;

 

塊地址根據檔案號和塊號可以查詢得到

select dbms_utility.make_data_block_address(file#, block#) from dual;

 

反過來根據資料塊地址也能查詢到檔案號和塊號

select dbms_utility.data_block_address_file(dba#) file#, dbms_utility.data_block_address_block(dba#) block# from dual;

 

執行完blockrecover塊恢復命令後,在開啟資料庫前可能還需要對資料檔案進行介質恢復

recover datafile 7;

 

三、壞塊恢復實驗

 

恢復是建立在歸檔日誌模式且有備份的前提下的,因此實驗前應確認當前為歸檔模式

archive log list;

 

建表空間

create tablespace blocktbs datafile '/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf' size 4m;

 

建測試使用者

create user u1 identified by u1 default tablespace blocktbs;

grant connect, resource to u1;

 

建表

create table u1.blocktab(a number, b varchar2(30));

 

插入模擬資料

declare

len number;

begin

for i in 1..1000 loop

len:=trunc(dbms_random.value(1, 30));

insert into u1.blocktab values(i, dbms_random.string('a', len));

end loop;

commit;

end;

/

 

檢視錶所在的檔案和資料塊

select distinct dbms_rowid.rowid_relative_fno(rowid) file#, dbms_rowid.rowid_block_number(rowid) block# from u1.blocktab order by 2;

 

     FILE#     BLOCK#

---------- ----------

  10             132

  10             133

  10             134

  10             135

 

檢視每個資料塊擁有的記錄數

select dbms_rowid.rowid_block_number(rowid) block#, count(*) block_records from u1.blocktab group by dbms_rowid.rowid_block_number(rowid) order by 1;

 

    BLOCK# BLOCK_RECORDS

---------- -------------

       132              304

       133              287

       134              295

       135              114

 

以上操作顯示,表blocktab中插入了1000條測試資料,共佔用4個資料塊,每個資料塊填滿(保持pctfree空閒)大約容納近300條記錄。

 

備份資料檔案

rman target /

backup datafile 10;

 

計算第132號資料塊的大概位置

show parameters db_block_size;

 

NAME                                     TYPE         VALUE

--------------------------------- --------- ----------

db_block_size                             integer         8192

 

select to_char(132*8192,'xxxxxx') from dual;

 

TO_CHAR(132*8192,'XXX

---------------------

 108000

 

用二進位制文字編輯器開啟10#檔案,找到地址108000位置後的資料,手動編輯修改,模擬壞塊

vim -b /home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

 

檔案將以二進位制形式開啟,用:%!xxd指令可顯示為十六進位制狀態,編輯後可用:%!xxd -r指令回到二進位制顯示狀態,最後用:wq儲存。

 

也可以用dd命令向指定塊寫入資料來模擬壞塊

dd if=/dev/zero of=/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf bs=8192 count=1 seek=132 conv=notrunc

 

重新整理資料庫快取

alter system flush buffer_cache;

 

再次查詢表

select count(*) from u1.blocktab;

 

提示壞塊錯誤

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 10, block # 132)

ORA-01110: data file 10: '/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf'

 

RMAN檢查此檔案壞塊

RMAN> backup validate check logical datafile 10;

 

Starting backup at 05-MAY-18

using target database control file instead of recovery catalog

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=6 device type=DISK

channel ORA_DISK_1: starting full datafile backup set

channel ORA_DISK_1: specifying datafile(s) in backup set

input datafile file number=00010 name=/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01

List of Datafiles

=================

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN

---- ------ -------------- ------------ --------------- ----------

10   FAILED 0              377          512             3433950  

  File Name: /home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

  Block Type Blocks Failing Blocks Processed

  ---------- -------------- ----------------

  Data       0              4              

  Index      0              0              

  Other      1              131            

 

validate found one or more corrupt blocks

See trace file /home/oracle/app/oracle/diag/rdbms/mes/mes/trace/mes_ora_7842.trc for details

Finished backup at 05-MAY-18

 

根據塊損壞情況,若提示檔案壞已不能訪問,則v$database_block_corruption中沒有記錄,如果RMAN還能夠訪問並檢查,則會在該檢視中列出壞塊資訊。

select * from v$database_block_corruption;

 

     FILE#     BLOCK#            BLOCKS CORRUPTION_CHANGE#  CORRUPTION_TYPE

---------- ---------- ---------- ------------------ ---------------------------

  10             132           1                        0  ALL ZERO

 

檢視損壞塊所涉及的資料庫物件

col tablespace_name for a20

col segment_name for a20

col segment_type for a20

col owner for a10

select tablespace_name, segment_type, owner, segment_name from dba_extents where file_id=10 and 132 between block_id and block_id+blocks-1;

 

TABLESPACE_NAME      SEGMENT_TYPE              OWNER      SEGMENT_NAME

-------------------- -------------------- ---------- --------------------

BLOCKTBS               TABLE                      U1           BLOCKTAB

 

查詢10#資料檔案的RMAN備份

RMAN> list backup of datafile 10;

 

 

List of Backup Sets

===================

 

 

BS Key  Type LV Size       Device Type Elapsed Time Completion Time

------- ---- -- ---------- ----------- ------------ ---------------

91      Full    1.10M      DISK        00:00:00     05-MAY-18     

        BP Key: 91   Status: AVAILABLE  Compressed: NO  Tag: TAG20180505T182704

        Piece Name: /home/oracle/app/oracle/flash_recovery_area/MES/backupset/2018_05_05/o1_mf_nnndf_TAG20180505T182704_fgv1qrdp_.bkp

  List of Datafiles in backup set 91

  File LV Type Ckp SCN    Ckp Time  Name

  ---- -- ---- ---------- --------- ----

  10      Full 3434217    05-MAY-18 /home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

 

備份的SCN是3434217,查詢該SCN之後的歸檔日誌備份

RMAN> list backup of archivelog from scn 3434217;

 

specification does not match any backup in the repository

 

表示此SCN之後的歸檔日誌沒有備份。

 

檢視此SCN之後的歸檔日誌是否存在

RMAN> list archivelog from scn 3434217;

 

查詢列出了在此SCN之後有三個歸檔日誌

Key     Thrd Seq     S Low Time

------- ---- ------- - ---------

1       1    32      A 05-MAY-18

        Name: /home/oracle/app/oracle/flash_recovery_area/MES/archivelog/2018_05_05/o1_mf_1_32_d1070kob_.arc

 

2       1    33      A 05-MAY-18

        Name: /home/oracle/app/oracle/flash_recovery_area/MES/archivelog/2018_05_05/o1_mf_1_33_d10nob7p_.arc

 

3       1    34      A 05-MAY-18

        Name: /home/oracle/app/oracle/flash_recovery_area/MES/archivelog/2018_05_05/o1_mf_1_34_d10oqlqv_.arc

 

資料塊當前日誌序列號

archive log list;

 

Database log mode               Archive Mode

Automatic archival               Enabled

Archive destination               USE_DB_RECOVERY_FILE_DEST

Oldest online log sequence   33

Next log sequence to archive 35

Current log sequence               35

 

資料塊當前的日誌序列號為3510#檔案的最新備份時的SCN之後的日誌檔案序列號為32333435都連續存在,因此可以判斷10#檔案的資料塊損壞可以恢復。另一種情況是備份時的SCN還處於當前聯機日誌中,當然也是可以恢復的。

 

執行RMAN的壞塊恢復

RMAN> blockrecover datafile 10 block 132;

 

Starting recover at 05-MAY-18

using target database control file instead of recovery catalog

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=34 device type=DISK

 

channel ORA_DISK_1: restoring block(s)

channel ORA_DISK_1: specifying block(s) to restore from backup set

restoring blocks of datafile 00010

channel ORA_DISK_1: reading from backup piece /home/oracle/app/oracle/flash_recovery_area/MES/backupset/2018_05_05/o1_mf_nnndf_TAG20180505T182704_fgv1qrdp_.bkp

channel ORA_DISK_1: piece handle=/home/oracle/app/oracle/flash_recovery_area/MES/backupset/2018_05_05/o1_mf_nnndf_TAG20180505T182704_fgv1qrdp_.bkp tag=TAG20180505T182704

channel ORA_DISK_1: restored block(s) from backup piece 1

channel ORA_DISK_1: block restore complete, elapsed time: 00:00:01

 

starting media recovery

media recovery complete, elapsed time: 00:00:03

 

Finished recover at 05-MAY-18

 

再次用RMAN檢查檔案塊狀態,可以看到已沒有壞塊

RMAN> backup validate check logical datafile 10;

 

Starting backup at 05-MAY-18

using channel ORA_DISK_1

channel ORA_DISK_1: starting full datafile backup set

channel ORA_DISK_1: specifying datafile(s) in backup set

input datafile file number=00010 name=/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01

List of Datafiles

=================

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN

---- ------ -------------- ------------ --------------- ----------

10   OK     0              377          512             3433950  

  File Name: /home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

  Block Type Blocks Failing Blocks Processed

  ---------- -------------- ----------------

  Data       0              5              

  Index      0              0              

  Other      0              130            

 

dbverify工具檢查也是完好的

[oracle@vm-ora11g-linux-6-1 桌面]$ dbv file=/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

 

DBVERIFY: Release 11.2.0.1.0 - Production on Sat May 5 20:19:27 2018

 

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

 

DBVERIFY - Verification starting : FILE = /home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

 

 

DBVERIFY - Verification complete

 

Total Pages Examined         : 512

Total Pages Processed (Data) : 5

Total Pages Failing   (Data) : 0

Total Pages Processed (Index): 0

Total Pages Failing   (Index): 0

Total Pages Processed (Other): 130

Total Pages Processed (Seg)  : 0

Total Pages Failing   (Seg)  : 0

Total Pages Empty            : 377

Total Pages Marked Corrupt   : 0

Total Pages Influx           : 0

Total Pages Encrypted        : 0

Highest block SCN            : 3433950 (0.3433950)

 

全表掃描資料已正常

select count(*) from u1.blocktab;

 

  COUNT(*)

----------

      1000

 

三、沒有備份情況下的塊恢復

 

在資料庫為非歸檔模式等沒有備份的情況下,壞塊的處理就是首先定位到有壞塊的表,透過設定10231事件跳過EXP匯出時的壞塊檢查,將能夠拯救的資料匯出,然後將損壞的表刪除,再透過IMP匯入將表和資料重新建立起來,以下舉例說明這一操作。

 

建表空間

create tablespace blocktbs datafile '/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf' size 4m;

 

建測試使用者

create user u1 identified by u1 default tablespace blocktbs;

grant connect, resource to u1;

 

建表

create table u1.blocktab(a number, b varchar2(30));

 

插入模擬資料

declare

len number;

begin

for i in 1..1000 loop

len:=trunc(dbms_random.value(1, 30));

insert into u1.blocktab values(i, dbms_random.string('a', len));

end loop;

commit;

end;

/

 

查詢表當前共有1000條記錄

select count(*) from u1.blocktab;

 

  COUNT(*)

----------

     1000

 

檢視錶所在的檔案和資料塊

select distinct dbms_rowid.rowid_relative_fno(rowid) file#, dbms_rowid.rowid_block_number(rowid) block# from u1.blocktab order by 2;

 

     FILE#     BLOCK#

---------- ----------

  10             131

  10             132

  10             134

  10             135

 

計算第131號資料塊的大概位置

show parameters db_block_size;

 

NAME                                     TYPE         VALUE

--------------------------------- --------- ----------

db_block_size                             integer         8192

 

select to_char(131*8192,'xxxxxx') from dual;

 

TO_CHAR(131*8192,'XXX

---------------------

 106000

 

用二進位制文字編輯器開啟10#檔案,找到地址106000位置後的資料,手動編輯修改,模擬壞塊

vim -b /home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

 

檔案將以二進位制形式開啟,用:%!xxd指令可顯示為十六進位制狀態,編輯後可用:%!xxd -r指令回到二進位制顯示狀態,最後用:wq儲存。

 

也可以用dd命令向指定塊寫入資料來模擬壞塊

dd if=/dev/zero of=/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf bs=8192 count=1 seek=131 conv=notrunc

 

重新整理資料庫快取

alter system flush buffer_cache;

 

再次查詢表

select count(*) from u1.blocktab;

 

提示壞塊錯誤

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 10, block # 131)

ORA-01110: data file 10: '/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf'

 

RMAN檢查此檔案壞塊

RMAN> backup validate check logical datafile 10;

 

Starting backup at 05-MAY-18

using target database control file instead of recovery catalog

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=98 device type=DISK

channel ORA_DISK_1: starting full datafile backup set

channel ORA_DISK_1: specifying datafile(s) in backup set

input datafile file number=00010 name=/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01

List of Datafiles

=================

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN

---- ------ -------------- ------------ --------------- ----------

10   FAILED 0              377          512             3442072  

  File Name: /home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

  Block Type Blocks Failing Blocks Processed

  ---------- -------------- ----------------

  Data       0              4              

  Index      0              0              

  Other      1              131            

 

validate found one or more corrupt blocks

See trace file /home/oracle/app/oracle/diag/rdbms/mes/mes/trace/mes_ora_48861.trc for details

Finished backup at 05-MAY-18

 

查詢RMAN檢查後存放壞塊資訊的檢視

select * from v$database_block_corruption;

 

     FILE#     BLOCK#            BLOCKS CORRUPTION_CHANGE#  CORRUPTION_TYPE

---------- ---------- ---------- ------------------ ---------------------------

  10             131            1                        0  ALL ZERO

 

跟蹤檔案mes_ora_48861.trc中也記錄了壞塊資訊。警告日誌檔案alert_mes.log中同樣可以看到壞塊資訊。

 

dbverify工具也可以提示壞塊資訊

[oracle@vm-ora11g-linux-6-1 桌面]$ dbv file=/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

 

DBVERIFY: Release 11.2.0.1.0 - Production on Sat May 5 22:02:28 2018

 

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

 

DBVERIFY - Verification starting : FILE = /home/oracle/app/oracle/oradata/mes/blocktbs01.dbf

Page 131 is marked corrupt

Corrupt block relative dba: 0x02800083 (file 10, block 131)

Completely zero block found during dbv:

 

 

 

DBVERIFY - Verification complete

 

Total Pages Examined         : 512

Total Pages Processed (Data) : 4

Total Pages Failing   (Data) : 0

Total Pages Processed (Index): 0

Total Pages Failing   (Index): 0

Total Pages Processed (Other): 130

Total Pages Processed (Seg)  : 0

Total Pages Failing   (Seg)  : 0

Total Pages Empty            : 377

Total Pages Marked Corrupt   : 1

Total Pages Influx           : 0

Total Pages Encrypted        : 0

Highest block SCN            : 3442072 (0.3442072)

 

檢視損壞塊所涉及的資料庫物件

col tablespace_name for a20

col segment_name for a20

col segment_type for a20

col owner for a10

select tablespace_name, segment_type, owner, segment_name from dba_extents where file_id=10 and 131 between block_id and block_id + blocks - 1;

 

TABLESPACE_NAME      SEGMENT_TYPE              OWNER      SEGMENT_NAME

-------------------- -------------------- ---------- --------------------

BLOCKTBS               TABLE                      U1           BLOCKTAB

 

此時是不允許exp匯出的,提示壞塊錯誤

[oracle@vm-ora11g-linux-6-1 桌面]$ exp \"sys/mesHz2 as sysdba\" file=/home/oracle/blocktab.dmp tables=u1.blocktab

 

Export: Release 11.2.0.1.0 - Production on Sat May 5 22:06:35 2018

 

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

 

 

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

Export done in UTF8 character set and AL16UTF16 NCHAR character set

server uses ZHS16GBK character set (possible charset conversion)

 

About to export specified tables via Conventional Path ...

Current user changed to U1

. . exporting table                       BLOCKTAB

EXP-00056: ORACLE error 1578 encountered

ORA-01578: ORACLE data block corrupted (file # 10, block # 131)

ORA-01110: data file 10: '/home/oracle/app/oracle/oradata/mes/blocktbs01.dbf'

Export terminated successfully with warnings.

 

損壞的是資料,我們可以設定內部事件,使exp跳過這些損壞的塊

alter system set events='10231 trace name context forever,level 10';

 

重新執行匯出命令

[oracle@vm-ora11g-linux-6-1 桌面]$ exp \"sys/mesHz2 as sysdba\" file=/home/oracle/blocktab.dmp tables=u1.blocktab

 

Export: Release 11.2.0.1.0 - Production on Sat May 5 22:11:47 2018

 

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

 

 

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

Export done in UTF8 character set and AL16UTF16 NCHAR character set

server uses ZHS16GBK character set (possible charset conversion)

 

About to export specified tables via Conventional Path ...

Current user changed to U1

. . exporting table                       BLOCKTAB        705 rows exported

EXP-00091: Exporting questionable statistics.

Export terminated successfully with warnings.

 

顯示成功匯出705條資料,這比原本1000條資料少了295條,因為沒有備份,這部分資料只能丟失了。

 

將表刪除

drop table u1.blocktab purge;

 

再重新imp匯入

[oracle@vm-ora11g-linux-6-1 桌面]$ imp \"sys/mesHz2 as sysdba\" file=/home/oracle/blocktab.dmp tables=blocktab fromuser=u1 touser=u1 ignore=y

 

Import: Release 11.2.0.1.0 - Production on Sat May 5 22:22:25 2018

 

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

 

 

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

 

Export file created by EXPORT:V11.02.00 via conventional path

import done in UTF8 character set and AL16UTF16 NCHAR character set

import server uses ZHS16GBK character set (possible charset conversion)

. importing U1's objects into U1

. . importing table                     "BLOCKTAB"        705 rows imported

Import terminated successfully without warnings.

 

檢視錶,恢復了705行資料

select count(*) from u1.blocktab;

 

  COUNT(*)

----------

       705

 

重新禁用壞塊跳過

alter system set events='10231 trace name context off';

 

此後,用RMANDBV檢查資料檔案可能仍然會提示有壞塊,也就是說檔案的壞塊位置已被標記,但表所在的資料塊,可能已經不是以前的位置了。

 

四、使用dbms_repair檢測和跳過壞塊

 

以上是透過設定10231內部事件,用exp匯出表資料後將表刪除,並用imp重新匯入表的方法重建表來恢復的。下面用Oracle提供的PL/SQL程式包dbms_repair來檢查和處理表和索引中出現的壞塊問題,包括標記和跳過壞塊。

 

建表空間

create tablespace testtbs datafile '/home/oracle/app/oracle/oradata/mes/testtbs01.dbf' size 2m;

 

建測試使用者

create user u1 identified by u1 default tablespace testtbs;

grant connect, resource to u1;

 

建測試表

create table u1.t1 tablespace testtbs as select * from scott.emp;

 

連續插入一批資料

insert into u1.t1 select * from u1.t1;

/

commit;

 

select count(*) from u1.t1;

 

  COUNT(*)

----------

      896

 

建立索引

create index u1.idx_t1_ename on u1.t1(ename);

 

檢視錶所在的檔案和資料塊

select distinct dbms_rowid.rowid_relative_fno(rowid) file#, dbms_rowid.rowid_block_number(rowid) block# from u1.t1 order by 2;

 

     FILE#     BLOCK#

---------- ----------

  10             131

  10             132

  10             133

  10             134

  10             135

  10             136

  10             137

 

檢視每個資料塊擁有的記錄數

select dbms_rowid.rowid_block_number(rowid) block#, count(*) block_records from u1.t1 group by dbms_rowid.rowid_block_number(rowid) order by 1;

 

    BLOCK# BLOCK_RECORDS

---------- -------------

       131               14

       132              170

       133              170

       134              170

       135              170

       136              170

       137               32

 

以上顯示錶u1.t1中包含896條測試資料,共佔用7個資料塊,每個資料塊填滿(保持pctfree空閒)大約容納170條記錄。

 

計算第135號資料塊的大概位置

show parameters db_block_size;

 

NAME                                     TYPE         VALUE

--------------------------------- --------- ----------

db_block_size                             integer         8192

 

select to_char(135 * 8192,'xxxxxx') from dual;

 

TO_CHAR

-------

 10e000

 

用二進位制文字編輯器開啟10#檔案,找到地址10e000位置後的資料,手動編輯修改,模擬壞塊

vim -b /home/oracle/app/oracle/oradata/mes/testtbs01.dbf

 

檔案將以二進位制形式開啟,用:%!xxd指令可顯示為十六進位制狀態,編輯後可用:%!xxd -r指令回到二進位制顯示狀態,最後用:wq儲存。

 

也可以用dd命令向指定塊寫入資料來模擬壞塊

dd if=/dev/zero of=/home/oracle/app/oracle/oradata/mes/testtbs01.dbf bs=8192 count=1 seek=135 conv=notrunc

 

重新整理資料庫快取

alter system flush buffer_cache;

 

查詢表記錄

select count(*) from u1.t1;

 

  COUNT(*)

----------

      896

 

提示壞塊錯誤

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 10, block # 135)

ORA-01110: data file 10: '/home/oracle/app/oracle/oradata/mes/testtbs01.dbf'

 

使用dbms_repair包:

 

建立管理表,這裡表名不可用其它名稱

表資料

exec dbms_repair.admin_tables('REPAIR_TABLE', 1, 1, 'users');

索引資料

exec dbms_repair.admin_tables('ORPHAN_TABLE', 2, 1, 'users');

 

檢查壞塊

set serveroutput on

declare

cc number;

begin

dbms_repair.check_object(schema_name => 'U1', object_name => 'T1', corrupt_count => cc);

dbms_output.put_line(to_char(cc));

end;

/

1

檢查結果提示有一個壞塊。

 

檢查完之後,在我們剛在建立的REPAIR_TABLE中檢視塊損壞資訊

col object_name for a20

col corrupt_description for a30

col repair_description for a30

select object_name, relative_file_id, block_id, marked_corrupt, corrupt_description, repair_description, check_timestamp from repair_table;

 

OBJECT_NAME               RELATIVE_FILE_ID   BLOCK_ID MARKED_CORRUPT                         CORRUPT_DESCRIPTION                  REPAIR_DESCRIPTION                    CHECK_TIMESTAMP

-------------------- ---------------- ---------- ------------------------------ ------------------------------ ------------------------------ ---------------

T1                                      10          135 TRUE                                                                  mark block software corrupt    05-MAY-18

 

用skip_corrupt_blocks跳過壞塊

exec dbms_repair.skip_corrupt_blocks(schema_name => 'U1', object_name => 'T1', flags => 1);

 

再次掃描表已經可查詢

select count(*) from u1.t1;

 

  COUNT(*)

----------

       726

 

但丟失了896 - 726 = 170行資料。

 

處理索引上的無效鍵值

declare

cc number;

begin

dbms_repair.dump_orphan_keys(schema_name => 'U1', object_name => 'IDX_T1_ENAME', object_type => 2, repair_table_name => 'REPAIR_TABLE', orphan_table_name => 'ORPHAN_TABLE', key_count => CC);

end;

/

 

select count(*) from orphan_table;

 

  COUNT(*)

----------

       170

 

170行無效索引,和上面我們看到的損失資料吻合,根據這個結果可以考慮是否需要重建索引。

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

相關文章