Oracle数据库坏块的恢复

模拟数据块坏块:

对于发生数据块不一致的数据块,如果当前数据库有备份且处于归档模式,那么就可以利用rman工具数据块恢复功能 对数据块进行恢复,这种方法最简单有效,而且可以在数据文件在线时进行,不会发生数据丢失。对于被有备份的数据库 发生数据块损坏,可能会发生数据的丢失或数据不丢失,这要根据发生坏块的所在的对象决定的,如索引块发生损坏,数据 就不会丢失,重建索引就可以了,发生数据丢失的多发生在表或分区表数据块上。

1.不丢数据的恢复方法

---使用rman工具的

blockrecover 

blockrecover datafile xx block xx;--修复单个坏块
blockrecover corruption list;--修复全部坏块

SQL> select * from livan.test;
select * from livan.test
                    *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 12)
ORA-01110: data file 6: ‘/u02/app/oradata/PSDB/livan_tbs01.dbf‘

[[email protected] u02]$ rman target /

Recovery Manager: Release 10.2.0.4.0 - Production on Thu Feb 5 17:02:23 2015

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

connected to target database: PSDB (DBID=1410134833)

RMAN> blockrecover datafile 6 block 12;

Starting blockrecover at 05-FEB-15
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: sid=142 devtype=DISK

channel ORA_DISK_1: restoring block(s)
channel ORA_DISK_1: specifying block(s) to restore from backup set
restoring blocks of datafile 00006
channel ORA_DISK_1: reading from backup piece /u02/PSDB_BACKUP/full_PSDB_870868610
channel ORA_DISK_1: restored block(s) from backup piece 1
piece handle=/u02/PSDB_BACKUP/full_PSDB_870868610 tag=TAG20150205T115650
channel ORA_DISK_1: block restore complete, elapsed time: 00:00:01

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

Finished blockrecover at 05-FEB-15

[[email protected] u02]$ sqlplus ‘/as sysdba‘

SQL*Plus: Release 10.2.0.4.0 - Production on Thu Feb 5 17:04:15 2015

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select * from livan.test;

        ID NAME
---------- ------------------------------
         1 beijing
         2 shanghai
         3 shandong

如果坏块上的表最近都没有更新,还可以利用bbed的copy命令来从一个最近的备份中copy过来一个数据块恢复,具体不演示。

2.有可能存在数据丢失的恢复(在没有备份没有归档的情况下)

---用户表数据损坏

<1>常情况下数据条目数

SQL> select count(*) from test;

  COUNT(*)
----------
     50604

<2>制作一个坏块

select rowid,
dbms_rowid.rowid_relative_fno(rowid) rel_fno,
dbms_rowid.rowid_block_number(rowid) blockno,
dbms_rowid.rowid_row_number(rowid) rowno
from livan.test;   

BBED> set dba 6,76
        DBA             0x0180004c (25165900 6,76)

BBED> d /v dba 6,76 offset 0
 File: /u02/app/oradata/PSDB/livan_tbs01.dbf (6)
 Block: 76      Offsets:    0 to  127  Dba:0x0180004c
-------------------------------------------------------
 06a20000 4c008001 d3220800 00000104 l .?.L...?......
 b8510000 01000000 ddce0000 b4220800 l 窺......菸..?..
 00000000 03003201 41008001 ffff0000 l ......2.A.......
 00000000 00000000 00000000 00800000 l ................
 b4220800 00000000 00000000 00000000 l ?..............
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00019200 l ................

 <16 bytes per line>

BBED> modify /x 12345 dba 6,76 offset 0
 File: /u02/app/oradata/PSDB/livan_tbs01.dbf (6)
 Block: 76               Offsets:    0 to  127           Dba:0x0180004c
------------------------------------------------------------------------
 01234500 4c008001 d3220800 00000104 b8510000 01000000 ddce0000 b4220800
 00000000 03003201 41008001 ffff0000 00000000 00000000 00000000 00800000
 b4220800 00000000 00000000 00000000 00000000 00000000 00000000 00000000
 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00019200 

 <32 bytes per line>

BBED> sum play
BBED-00202: invalid parameter (play)

BBED> sum apply
Check value for File 6, Block 76:
current = 0xd0fa, required = 0xd0fa

SQL> alter system flush buffer_cache;

System altered.

SQL> select count(*) from test;
select count(*) from test
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 76)
ORA-01110: data file 6: ‘/u02/app/oradata/PSDB/livan_tbs01.dbf‘

发现我们第6个文件第76号数据块损坏,报ORA-0178错误,我们知掉只要数据库报ORA-01578错误,
说明该数据块已经被标识为:"software corrupt"

<3>确认坏块的类型

SQL> select segment_name,partition_name,segment_type,owner,tablespace_name
  2  from sys.dba_extents
  3  where file_id=&AFN
  4  and &bad_block_id between block_id and block_id + blocks-1;
Enter value for afn: 6
old   3: where file_id=&AFN
new   3: where file_id=6
Enter value for bad_block_id: 76
old   4: and &bad_block_id between block_id and block_id + blocks-1
new   4: and 76 between block_id and block_id + blocks-1

SEGMENT_NAME    PARTITION_NAME       SEGMENT_TYPE       OWNER      TABLESPACE_NAME
--------------- -------------------- ------------------ ---------- ------------------------------
TEST                                 TABLE              LIVAN      LIVAN_TBS

经查我们的数据损坏坏位于我们的用户表上,无备份数据会丢失。

<4>标记坏块为"software corrupt"

在第2步的时候全表扫描时已经报ORA-01578错误,说明该数据块已经被标识为:"software corrupt", 正常情况下可以跳过这步。 我们使用dbms_repair包演示标记坏块为"software corrupt"

使用dbms_repair包可参考:http://blog.itpub.net/8494287/viewspace-1357457/

--利用dbms_repair包必须先创建repair table两个表:

SQL> begin
  2  dbms_repair.admin_tables(
  3  table_name=>‘REPAIR_TABLE‘,
  4  table_type=>dbms_repair.repair_table,
  5  action=>dbms_repair.create_action,
  6  tablespace=>‘LIVAN_TBS‘);
  7  end;
  8  /

PL/SQL procedure successfully completed.

SQL>  col object_name for a20
SQL> select owner,object_name,object_type
  2  from dba_objects
  3  where object_name like ‘%REPAIR_TABLE%‘;

OWNER                          OBJECT_NAME          OBJECT_TYPE
------------------------------ -------------------- -------------------
SYS                            REPAIR_TABLE         TABLE
SYS                            DBA_REPAIR_TABLE     VIEW

--再创建orphan key table

SQL> begin
  2  dbms_repair.admin_tables(
  3  table_type=>dbms_repair.orphan_table,
  4  action=>dbms_repair.create_action,
  5  tablespace=>‘LIVAN_TBS‘);
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> select owner,object_name,object_type
  2  from dba_objects
  3  where object_name like ‘%ORPHAN_KEY_TABLE%‘;

OWNER                          OBJECT_NAME          OBJECT_TYPE
------------------------------ -------------------- -------------------
SYS                            ORPHAN_KEY_TABLE     TABLE
SYS                            DBA_ORPHAN_KEY_TABLE VIEW

--检查对象,检查结果会放到我们之前创建的repair_table中

SQL> set serveroutput on
SQL> declare
  2  rpr_count int;
  3  begin
  4  rpr_count:=0;
  5  dbms_repair.check_object(
  6  schema_name=>‘LIVAN‘,
  7  object_name=>‘TEST‘,
  8  repair_table_name=>‘REPAIR_TABLE‘,
  9  corrupt_count=>rpr_count);
 10  dbms_output.put_line(‘repair count:‘||to_char(rpr_count));
 11  end;
 12  /
repair count:1

PL/SQL procedure successfully completed.

检查出有1个坏块

--检查校验的坏块结果

SQL> select object_name,block_id,corrupt_type,marked_corrupt,
  2  corrupt_description,repair_description
  3  from repair_table;

OBJECT_NAM   BLOCK_ID CORRUPT_TYPE MARKED_COR CORRUPT_DESCRIP REPAIR_DESCRIPTION
---------- ---------- ------------ ---------- --------------- ------------------------------
TEST               76         6148 TRUE                       mark block software corrupt

我们知道当marked_corrupt为TRUE时,标识这个数据块已经被标识过software corrupt

---标识坏块为software corrupt(重新演示一下)

SQL> declare
  2  fix_count int;
  3  begin
  4  fix_count:=0;
  5  dbms_repair.fix_corrupt_blocks(
  6  schema_name=>‘LIVAN‘,
  7  object_name=>‘TEST‘,
  8  object_type=>dbms_repair.table_object,
  9  repair_table_name=>‘REPAIR_TABLE‘,
 10  fix_count=>fix_count);
 11  dbms_output.put_line(‘fix count:‘||to_char(fix_count));
 12  end;
 13  /
fix count:0

PL/SQL procedure successfully completed.

--再次检查,因为已经被标志为software corrupt,所以在此标志也没什么变化

SQL> select object_name,block_id,corrupt_type,marked_corrupt,
  2  corrupt_description,repair_description
  3  from repair_table;

OBJECT_NAM   BLOCK_ID CORRUPT_TYPE MARKED_COR CORRUPT_DESCRIP REPAIR_DESCRIPTION
---------- ---------- ------------ ---------- --------------- ------------------------------
TEST               76         6148 TRUE                       mark block software corrupt

未被标志为oftware corrupt ,marked_corrupt列会显示FALSE

<5>检查其他关联对象

检查有多少个索引项指向了坏块的记录

SQL> select index_name from dba_indexes
  2  where table_name in (select distinct object_name from repair_table);

INDEX_NAME
------------------------------
INDEX_TEST

查询发现有一个索引指向这个坏块

--检查都有多少索引数据

SQL> set serveroutput on
SQL> declare
  2  key_count int;
  3  begin
  4  key_count:=0;
  5  dbms_repair.dump_orphan_keys(
  6  schema_name=>‘LIVAN‘,
  7  object_name=>‘INDEX_TEST‘,
  8  object_type=>dbms_repair.index_object,
  9  repair_table_name=>‘REPAIR_TABLE‘,
 10  orphan_table_name=>‘ORPHAN_KEY_TABLE‘,
 11  key_count=>key_count);
 12  dbms_output.put_line(‘orphan key count:‘||to_char(key_count));
 13  end;
 14  /
orphan key count:146

PL/SQL procedure successfully completed.

SQL> select index_name,count(*) from orphan_key_table
  2  group by index_name;

INDEX_NAME                       COUNT(*)
------------------------------ ----------
INDEX_TEST                            146

可以看到有146条数据指向坏块

<6>使用dbms_repair.skip_corrupt_blocks或10231事件方式跳过坏块

SQL> select count(*) from livan.test;
select count(*) from livan.test
                           *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 76)
ORA-01110: data file 6: ‘/u02/app/oradata/PSDB/livan_tbs01.dbf‘

SQL> begin
  2  dbms_repair.skip_corrupt_blocks(
  3  schema_name=>‘LIVAN‘,
  4  object_name=>‘TEST‘,
  5  object_type=>dbms_repair.table_object,
  6  flags=>dbms_repair.skip_flag);
  7  end;
  8  /

PL/SQL procedure successfully completed.

SQL> select count(*) from livan.test;

  COUNT(*)
----------
     50458

可以看到当执行完dbms_repair.skip_corrupt_blocks数据可以正常访问了,只是统计出来的数据比原先
少了146条(50604-50458),也就是我们坏块上的数据没有统计,被跳过了。

---使用10231事件跳过

SQL> select count(*) from livan.test;

  COUNT(*)
----------
     50458

SQL> begin
  2  dbms_repair.skip_corrupt_blocks(
  3  schema_name=>‘LIVAN‘,
  4  object_name=>‘TEST‘,
  5  object_type=>dbms_repair.table_object,
  6  flags=>dbms_repair.noskip_flag);
  7  end;
  8  /

PL/SQL procedure successfully completed.

SQL> select count(*) from livan.test;
select count(*) from livan.test
                           *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 76)
ORA-01110: data file 6: ‘/u02/app/oradata/PSDB/livan_tbs01.dbf‘

SQL> alter session set events ‘10231 trace name context forever,level 10‘; 

Session altered.

SQL> select count(*) from livan.test;

  COUNT(*)
----------
     50458

SQL> alter session set events ‘10231 trace name context off‘;

Session altered.  

<7>使用CTAS方式重建表及索引

SQL> create table test_bak as select * from test;

Table created.

SQL> create index idx_test_bak on test_bak(object_id);

Index created.

--重建索引语句
SQL> alter index index_test rebuild online;

Index altered.

<8>使用重建对象的freelists方式修复原表

使用这种方式防止坏块以后被加入到freelists中 注意这个方法只适用于段空间手动管理的表空间(SEGMENT SPACE MANAGEMENT MANUAL), 否则会报ORA-10614: Operation not allowed on this segment 错误

SQL> begin
  2  dbms_repair.rebuild_freelists(
  3  schema_name=>‘LIVAN‘,
  4  object_name=>‘TEST‘,
  5  object_type=>dbms_repair.table_object);
  6  end;
  7  /
begin
*
ERROR at line 1:
ORA-10614: Operation not allowed on this segment
ORA-06512: at "SYS.DBMS_REPAIR", line 401
ORA-06512: at line 2

<9>坏块中的数据

如果坏块中的数据不可丢失,只能尝试其他方法从恢复坏块内容,这其中也有一些第三方付费工具可使用, 也可进行以下尝试:

*尝试从索引内容中恢复出索引列的内容

*尝试使用logminer,从日志中挖掘

*联系Oracle Support,会有些工具解释数据块中的内容。

时间: 2024-10-10 06:08:16

Oracle数据库坏块的恢复的相关文章

12 oracle 数据库坏块--物理坏块-ORA-01578/ORA-01110

oracle 数据库坏块--物理坏块 数据坏块的类型物理坏块:通常是由于硬件损坏如磁盘异常导致.内存有问题.存储链有问题. IO有问题.文件系统有问题. Oracle本身的问题等逻辑坏块:可能都是软件问题导致通常是由于oracle bug导致,比如data block和index block数据不一致第三方软件或者硬件造成的物理损坏物理数据坏块的场景常见的物理坏块(Physical Block Corruptions)有块头和块尾信息不一致(Fractured/Incomplete),check

使用BBED模拟Oracle数据库坏块

BBED(OracleBlockBrowerandEDitor Tool),用来直接查看和修改数据文件数据的一个工具,是Oracle一款内部工具,可以直接修改Oracle数据文件块的内容,在一些极端恢复场景下比较有用.该工具不受Oracle支持,所以默认是没有生成可执行文件的,在使用前需要重新连接. 1.安装BBED [[email protected] lib]$ pwd /u02/app/product/10.2.0/db_1/rdbms/lib [[email protected] lib

对Oracle数据库坏块的理解

1.物理坏块和逻辑坏块 在数据库中有一个概念叫做数据块的一致性,Oracle的数据块的一致性包括了两个层次:物理一致性和逻辑一致性,如果一个数据块在这两个层次上存在不一致性,那就对应到了我们今天要要说的物理坏块和逻辑坏块. 在每一个数据块的头部有一个校验和字段,每当数据块要被写回磁盘前,Oracle都会重新计算 这个数据块的校验和,并记录到这个字段最终写会磁盘.下次数据块被读入内存,Oracle会重新 计算数据块的校验和,并和块头的字段相比较,如果有差异,Oracle就知道这个数据块有错误, 会

数据库坏块,怎么办?

在DBA的工作中,应该怎么处理oracle数据库坏块,我介绍一下大概一个思路: 1.检查数据块是否损坏: 利用RMAN对数据库进行备份时: 通过ANALYZE命令对表进行分析时: 通过dbv工具对数据文件进行校验时: 通过SQL命令访问数据文件时. 2.数据库坏块,进行恢复,块介质恢复需求满足以下条件: 数据库的日志模式必须是归档模式,而且数据库服务的状态是open或mount: 对数据库必须进行过0级或full备份,且备份文件是可用的. 数据库的flashback功能必须是enabled: 数

记一次存储故障导致数据库坏块处理过程

记一次存储故障导致数据库坏块处理过程 线上架构说明:     IBM DS4800存储一套     P560小机HA架构一套     两个数据库资源组平时run在HA架构中的任意一台中,资源组全部使用共享存储 问题描述: 由于存储在数据库运行过程中发生了异常宕机,导致两个库存在不同程度的坏块 错误信息及解决过程 数据库A: A:root:/db2dumph/istclhis > 2016-04-09-04.26.10.787138   Instance:istclhis   Node:000 P

Veritas Netbackup Oracle数据库本机备份恢复

概述: 本次实验环境采用Veritas Netbackup 7.7.3软件版本,对Redhat Linux Oracle数据库的备份和恢复. 操作系统 主机名 IP地址 Windows Server 2008R2  nbumaster 192.168.60.59 Redhat Linux 6.5 x86_64 rhel6 192.168.60.100 Oracle备份恢复实验拓扑: 备份RedHat Linux环境下的Oracle 11gR2数据库到Master Server端: 通过Maste

Oracle数据库中闪回恢复的详细分析

Oracle9i开始提供闪回查询,以便能在需要的时候查到过去某个时刻的一致性数据,这是通过Undo实现的.这个功能有很大的限制,就是相关事务的undo不能被覆盖,否则就无力回天了.oracle10g大大的增强了闪回查询的功能,并且提供了将整个数据库回退到过去某个时刻的能力,这是通过引入一种新的flashback log实现的. flashback log有点类似redo log,只不过redo log将数据库往前滚,flashback log则将Oracle数据库往后滚.为了保存管理和备份恢复相

【转】基于RMAN实现坏块介质恢复(blockrecover)

本文转自:乐沙弥的世界 对于物理损坏的数据块,我们可以通过RMAN块介质恢复(BLOCK MEDIA RECOVERY)功能来完成受损块的恢复,而不需要恢复整个数据库或所有文件来修复这些少量受损的数据块.恢复整个数据库或数据文件那不是大炮用来打蚊子,有点不值得!但前提条件是你得有一个可用的RMAN备份存在,因此,无论何时备份就是一切.本文演示了产生坏块即使用RMAN实现坏块恢复的全过程. 1.创建演示环境 SQL> select * from v$version where rownum<2;

oracle数据坏块检测

1.使用dbv检查 D:\oradata\eygle>dbv file=EYGLE.DBF blocksize=8192 DBVERIFY: Release 10.1.0.4.0 - Production on 星期六 6月 11 17:36:37 2005 Copyright (c) 1982, 2004, Oracle.  All rights reserved. DBVERIFY - 开始验证: FILE = EYGLE.DBF 页 219 标记为损坏 Corrupt block rela