模拟数据块坏块:

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

1.不丢数据的恢复方法

---使用rman工具的

blockrecover 

blockrecover datafile xx block xx;--修复单个坏块
blockrecover corruption list;--修复全部坏块 SQL> select * from livan.test;
select * from livan.test
*
ERROR at line :
ORA-: ORACLE data block corrupted (file # , block # )
ORA-: data file : '/u02/app/oradata/PSDB/livan_tbs01.dbf'
[oracle@std u02]$ rman target /

Recovery Manager: Release 10.2.0.4. - Production on Thu Feb  :: 

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

connected to target database: PSDB (DBID=)

RMAN> blockrecover datafile  block ;

Starting blockrecover at -FEB-
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: sid= 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
channel ORA_DISK_1: reading from backup piece /u02/PSDB_BACKUP/full_PSDB_870868610
channel ORA_DISK_1: restored block(s) from backup piece
piece handle=/u02/PSDB_BACKUP/full_PSDB_870868610 tag=TAG20150205T115650
channel ORA_DISK_1: block restore complete, elapsed time: :: starting media recovery
media recovery complete, elapsed time: :: Finished blockrecover at -FEB-
[oracle@std u02]$ sqlplus '/as sysdba'

SQL*Plus: Release 10.2.0.4. - Production on Thu Feb  :: 

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

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4. - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options SQL> select * from livan.test; ID NAME
---------- ------------------------------
beijing
shanghai
shandong

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

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

---用户表数据损坏

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

SQL> select count(*) from test;

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

<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 ,
DBA 0x0180004c ( ,) BBED> d /v dba , offset
File: /u02/app/oradata/PSDB/livan_tbs01.dbf ()
Block: Offsets: to Dba:0x0180004c
-------------------------------------------------------
06a20000 4c008001 d3220800 l .?.L...?......
b8510000 ddce0000 b4220800 l 窺......菸..?..
ffff0000 l .......A.......
l ................
b4220800 l ?..............
l ................
l ................
l ................ < bytes per line> BBED> modify /x dba , offset
File: /u02/app/oradata/PSDB/livan_tbs01.dbf ()
Block: Offsets: to Dba:0x0180004c
------------------------------------------------------------------------
4c008001 d3220800 b8510000 ddce0000 b4220800
ffff0000
b4220800 < bytes per line> BBED> sum play
BBED-: invalid parameter (play) BBED> sum apply
Check value for File , Block :
current = 0xd0fa, required = 0xd0fa SQL> alter system flush buffer_cache; System altered. SQL> select count(*) from test;
select count(*) from test
*
ERROR at line :
ORA-: ORACLE data block corrupted (file # , block # )
ORA-: data file : '/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
from sys.dba_extents
where file_id=&AFN
and &bad_block_id between block_id and block_id + blocks-;
Enter value for afn:
old : where file_id=&AFN
new : where file_id=
Enter value for bad_block_id:
old : and &bad_block_id between block_id and block_id + blocks-
new : and between block_id and block_id + blocks- 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
dbms_repair.admin_tables(
table_name=>'REPAIR_TABLE',
table_type=>dbms_repair.repair_table,
action=>dbms_repair.create_action,
tablespace=>'LIVAN_TBS');
end;
/ PL/SQL procedure successfully completed. SQL> col object_name for a20
SQL> select owner,object_name,object_type
from dba_objects
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
dbms_repair.admin_tables(
table_type=>dbms_repair.orphan_table,
action=>dbms_repair.create_action,
tablespace=>'LIVAN_TBS');
end;
/ PL/SQL procedure successfully completed. SQL> select owner,object_name,object_type
from dba_objects
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
rpr_count int;
begin
rpr_count:=;
dbms_repair.check_object(
schema_name=>'LIVAN',
object_name=>'TEST',
repair_table_name=>'REPAIR_TABLE',
corrupt_count=>rpr_count);
dbms_output.put_line('repair count:'||to_char(rpr_count));
end;
/
repair count: PL/SQL procedure successfully completed.

检查出有1个坏块

--检查校验的坏块结果

SQL> select object_name,block_id,corrupt_type,marked_corrupt,
corrupt_description,repair_description
from repair_table; OBJECT_NAM BLOCK_ID CORRUPT_TYPE MARKED_COR CORRUPT_DESCRIP REPAIR_DESCRIPTION
---------- ---------- ------------ ---------- --------------- ------------------------------
TEST TRUE mark block software corrupt

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

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

SQL> declare
fix_count int;
begin
fix_count:=;
dbms_repair.fix_corrupt_blocks(
schema_name=>'LIVAN',
object_name=>'TEST',
object_type=>dbms_repair.table_object,
repair_table_name=>'REPAIR_TABLE',
fix_count=>fix_count);
dbms_output.put_line('fix count:'||to_char(fix_count));
end;
/
fix count: PL/SQL procedure successfully completed.

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

SQL> select object_name,block_id,corrupt_type,marked_corrupt,
corrupt_description,repair_description
from repair_table; OBJECT_NAM BLOCK_ID CORRUPT_TYPE MARKED_COR CORRUPT_DESCRIP REPAIR_DESCRIPTION
---------- ---------- ------------ ---------- --------------- ------------------------------
TEST TRUE mark block software corrupt

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

<5>检查其他关联对象

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

SQL> select index_name from dba_indexes
where table_name in (select distinct object_name from repair_table); INDEX_NAME
------------------------------
INDEX_TEST

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

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

SQL> set serveroutput on
SQL> declare
key_count int;
begin
key_count:=;
dbms_repair.dump_orphan_keys(
schema_name=>'LIVAN',
object_name=>'INDEX_TEST',
object_type=>dbms_repair.index_object,
repair_table_name=>'REPAIR_TABLE',
orphan_table_name=>'ORPHAN_KEY_TABLE',
key_count=>key_count);
dbms_output.put_line('orphan key count:'||to_char(key_count));
end;
/
orphan key count: PL/SQL procedure successfully completed. SQL> select index_name,count(*) from orphan_key_table
group by index_name; INDEX_NAME COUNT(*)
------------------------------ ----------
INDEX_TEST

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

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

SQL> select count(*) from livan.test;
select count(*) from livan.test
*
ERROR at line :
ORA-: ORACLE data block corrupted (file # , block # )
ORA-: data file : '/u02/app/oradata/PSDB/livan_tbs01.dbf' SQL> begin
dbms_repair.skip_corrupt_blocks(
schema_name=>'LIVAN',
object_name=>'TEST',
object_type=>dbms_repair.table_object,
flags=>dbms_repair.skip_flag);
end;
/ PL/SQL procedure successfully completed. SQL> select count(*) from livan.test; COUNT(*)
----------

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

---使用10231事件跳过

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

  COUNT(*)
---------- SQL> begin
dbms_repair.skip_corrupt_blocks(
schema_name=>'LIVAN',
object_name=>'TEST',
object_type=>dbms_repair.table_object,
flags=>dbms_repair.noskip_flag);
end;
/ PL/SQL procedure successfully completed. SQL> select count(*) from livan.test;
select count(*) from livan.test
*
ERROR at line :
ORA-: ORACLE data block corrupted (file # , block # )
ORA-: data file : '/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(*)
---------- 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
dbms_repair.rebuild_freelists(
schema_name=>'LIVAN',
object_name=>'TEST',
object_type=>dbms_repair.table_object);
end;
/
begin
*
ERROR at line :
ORA-: Operation not allowed on this segment
ORA-: at "SYS.DBMS_REPAIR", line
ORA-: at line

<9>坏块中的数据

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

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

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

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

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

  1. undo丢失恢复异常恢复,运维DBA反映Oracle数据库无法启动报错ORA-01157 ORA-01110,分析原因为Oracle数据库坏块导致

    本文转自 惜纷飞 大师. 模拟基表事务未提交数据库crash,undo丢失恢复异常恢复,运维DBA反映Oracle数据库无法启动报错ORA-01157 ORA-01110,分析原因为Oracle数据库 ...

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

    oracle 数据库坏块--物理坏块 数据坏块的类型物理坏块:通常是由于硬件损坏如磁盘异常导致.内存有问题.存储链有问题. IO有问题.文件系统有问题. Oracle本身的问题等逻辑坏块:可能都是软件 ...

  3. 13 oracle数据库坏块-逻辑坏块(模拟/修复)

    13 oracle数据库坏块-逻辑坏块 逻辑数据坏块的场景1)oracle bug也可能导致逻辑坏块的产生. 特别是parallel dml. 例如:Bug 5621677 Logical corru ...

  4. 对Oracle数据库坏块的理解

    1.物理坏块和逻辑坏块 在数据库中有一个概念叫做数据块的一致性,Oracle的数据块的一致性包括了两个层次:物理一致性和逻辑一致性,如果一个数据块在这两个层次上存在不一致性,那就对应到了我们今天要要说 ...

  5. 使用BBED模拟Oracle数据库坏块

    BBED(OracleBlockBrowerandEDitor Tool),用来直接查看和修改数据文件数据的一个工具,是Oracle一款内部工具,可以直接修改Oracle数据文件块的内容,在一些极端恢 ...

  6. 使用不同用户对Oracle数据库进行异机恢复,失败,错误:Backup file not found in NetBackup catalog

    最近做某数据库恢复演练,数据库版本是10.2.0.4,恢复控制文件一直报错,报错如下,经过反复折腾,原来恢复机上oracle用户不是oracle导致(我的是oraclev4),查看源库oracle用户 ...

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

    本文转自:乐沙弥的世界 对于物理损坏的数据块,我们可以通过RMAN块介质恢复(BLOCK MEDIA RECOVERY)功能来完成受损块的恢复,而不需要恢复整个数据库或所有文件来修复这些少量受损的数据 ...

  8. Oracle 处理坏块

    本文主要介绍如何去处理在Oracle数据库中出现坏块的问题,对于坏块产生在不同的对象上,处理的方法会有所不同,本文将大致对这些方法做一些介绍.因为数据库运行时间长了,由于硬件设备的老化,出现坏块的几率 ...

  9. Oracle数据库的后备和恢复————关于检查点的一些知识

    当我们使用一个数据库时,总希望数据库的内容是可靠的.正确的,但由于计算机系统的故障(硬件故障.软件故障.网络故障.进程故障和系统故障)影响数据库系统的操作,影响数据库中数据的正确性,甚至破坏数据库,使 ...

随机推荐

  1. [Algorithm] 字符串匹配算法——KMP算法

    1 字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串& ...

  2. 一些PHP性能优化汇总

    PHP优化对于PHP的优化主要是对php.ini中的相关主要参数进行合理调整和设置,以下我们就来看看php.ini中的一些对性能影响较大的参数应该如何设置. # vi /etc/php.ini (1) ...

  3. Linux网络下载命令 wget 简介

    wget 是一个命令行的下载工具.对于我们这些 Linux 用户来说,几乎每天都在使用它.下面为大家介绍几个有用的 wget 小技巧,可以让你更加高效而灵活的使用 wget. $ wget -r -n ...

  4. Windows7 + Ubuntu双系统安装过程记录

    本文为在已安装Windows7系统的前提下安装Ubuntu Kylin 14.10系统的过程以及期间出现的各种问题的记录. Ubuntu系统下载 Ubuntu Kylin中文官方网站:http://w ...

  5. ASP.NET MVC中的两个Action之间值的传递--TempData

    一. ASP.NET MVC中的TempData 在ASP.NET MVC框架的ControllerBase中存在一个叫做TempData的Property,它的类型为TempDataDictiona ...

  6. struts2 国际化

    国际化概述: 软件国际化:一个软件根据来访者地区不同,显示不同语言. 国际化: * 必须有一组资源包: * 一组属性文件命名: 基本名称_语言(小写)_国家(大写).properties * 如:me ...

  7. mplayer-1.3.0-2016-09-01.7z

    鼠标右键 快速定位 左SHIFT 记录开始时间 左CTRL 记录结束时间 右CTRL 复制开始结束时间 00:00:00.000 00:00:00.000 右SHIFT 生成视频剪切命令保存到 _cu ...

  8. 进程互斥和fork

    自父进程继承 进程的资格(真实(real)/有效(effective)/已保存(saved) 用户号(UIDs)和组号(GIDs)) 环境(environment) 堆栈 内存 打开文件的描述符(注意 ...

  9. C#设计模式之工厂方法

    工厂方法模式: 1.不再提供一个按钮工厂类来统一负责所有产品的创建,而是将具体按钮的创建过程交给专门的工厂子类去完成 如果出现新的按钮类型,只需要为这种新类型的按钮定义一个具体的工厂类就可以创建该新按 ...

  10. LeetCode之237. Delete Node in a Linked List

    ------------------------------------------------ 因为不知道前序是谁,所以只好采用类似于数组实现的列表移动值, 又因为如果当前是最后一个元素了但是已经没 ...