Oracle坏块问题处理

曾经遇到过ORA-8103,01578的坏块错误记录下方法

 

首先,制造坏块

select tablespace_name,extent_management,SEGMENT_SPACE_MANAGEMENT from dba_tablespaces where tablespace_name='ETMCDB';
TABLESPACE_NAME EXTENT_MAN SEGMEN
------------------------------ ---------- ------
ETMCDB LOCAL AUTO
 
create table t1 (id number, c1 char(2000), c2 char(2000), c3 char(2000)) tablespace ETMCDB;
insert into t1 VALUES (1, 'A', 'A', 'A');
insert into t1 VALUES (2, 'A', 'A', 'A');
insert into t1 VALUES (3, 'A', 'A', 'A');
insert into t1 VALUES (4, 'A', 'A', 'A');
insert into t1 VALUES (5, 'A', 'A', 'A');
insert into t1 VALUES (6, 'A', 'A', 'A');
insert into t1 VALUES (7, 'A', 'A', 'A');
commit;
 
select id,rowid,dbms_rowid.rowid_relative_fno(rowid)||'_'||dbms_rowid.rowid_block_number(rowid) from t1;
ID ROWID DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID)||'_'||DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------ ---------------------------------------------------------------------------------
1 AAAOZnAAHAAAAAUAAA 7_20
2 AAAOZnAAHAAAAAVAAA 7_21
3 AAAOZnAAHAAAAAWAAA 7_22
4 AAAOZnAAHAAAAAXAAA 7_23
5 AAAOZnAAHAAAAAYAAA 7_24
6 AAAOZnAAGAAAABhAAA 6_97
7 AAAOZnAAGAAAABiAAA 6_98
7 rows selected.
 
SQL> select file#,name from v$datafile;
FILE# NAME
---------- -----------------------
7 /u02/oradata/ETMCDB02.dbf
 
SQL> shutdown immediate;

修改Checksum的值 

导出第31个块(算上os header block,物理上是32个块)来把它的变成坏块,使用dd考出data block 【更多关于DD请参考这里】

node1*orcl-/u02/oradata >dd if=/u02/oradata/ETMCDB02.dbf f=/u02/oradata/ETMCDB02_7_21.dd skip=21 bs=8192 count=1

1+0 records in

1+0 records out

8192 bytes (8.2 kB) copied, 0.00417351 seconds, 2.0 MB/s

这里涉及到了notrunc模式,如果没有指定notrunc的话那么需要再dd出65505个块,

node1*orcl-/u02/oradata >dd if=/u02/oradata/ETMCDB02.dbf f=/u02/oradata/ETMCDB02_7_65505.dd skip=22 bs=8192 count=65505

原因

node1*orcl-/home/oracle >ls -al /u02/oradata/

total 1159260

-rw-r--r-- 1 oracle dba 8192 Nov 15 15:23 ETMCDB02_7_21.dd

-rw-r----- 1 oracle dba 536879104 Nov 15 14:51 ETMCDB02.dbf

SQL> select (536879104-32*8192)/8192 from dual;

(536879104-32*8192)/8192

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

65505

也可以不用这么麻烦,可以在导回时使用notrunc方法

之后用Ultraedit打开修改offset 16随便一个>0的数值,然后传回

node1*orcl-/u02/oradata > dd if=/u02/oradata/ETMCDB02_7_21.dd f=/u02/oradata/ETMCDB02.dbf seek=21 bs=8192 count=1 conv=notrunc

这里还有个小技巧就是直接用Ultraedit打开确定文件7号ETMCDB02.dbf后在UE中按CTRL+G,输入这个 块号*块大小的结果就可以了,比如这个例子就是21*8192

SQL> startup
 
SQL> select * from t1;
ERROR:
ORA-01578: ORACLE data block corrupted (file # 7, block # 21)
ORA-01110: data file 7: '/u02/oradata/ETMCDB02.dbf'
no rows selected
 
SQL> SELECT tablespace_name, owner,segment_name,segment_type FROM dba_extents
        WHERE file_id = &file and &block between block_id AND block_id + blocks - 1 ;
Enter value for file: 7
Enter value for block: 21
old   1: SELECT tablespace_name, owner,segment_name,segment_type FROM dba_extents
           WHERE file_id = &file and &block between block_id AND block_id + blocks - 1
new   1: SELECT tablespace_name, owner,segment_name,segment_type FROM dba_extents
           WHERE file_id = 7 and 21 between block_id AND block_id + blocks - 1
 
TABLESPACE OWNER      SEGMENT_NAME         SEGMENT_TYPE
---------- ---------- -------------------- ------------------
ETMCDB     XXD        T1                 TABLE
node1*orcl-/u02/oradata >dbv file=ETMCDB02.dbf blocksize=8192

DBVERIFY: Release 10.2.0.1.0 - Production on Wed Nov 17 18:53:08 2010

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

DBVERIFY - Verification starting : FILE = ETMCDB02.dbf

Page 21 is marked corrupt

Corrupt block relative dba: 0x01c00015 (file 7, block 21)

Bad header found during dbv:

Data in bad block:

type: 6 format: 2 rdba: 0x01c00015

last change scn: 0x0000.005552a8 seq: 0x1 flg: 0x02

spare1: 0x0 spare2: 0x0 spare3: 0x0

consistency value in tail: 0x52a80601

check value in block header: 0x11

block checksum disabled

DBVERIFY - Verification complete

Total Pages Examined : 640

Total Pages Processed (Data) : 461

Total Pages Failing (Data) : 0

Total Pages Processed (Index): 1

Total Pages Failing (Index): 0

Total Pages Processed (Other): 45

Total Pages Processed (Seg) : 0

Total Pages Failing (Seg) : 0

Total Pages Empty : 132

Total Pages Marked Corrupt : 1

Total Pages Influx : 0

Highest block SCN : 5591720 (0.5591720)



使用DBMS_REPAIR “修复”坏块 


set serveroutput on
 
BEGIN
DBMS_REPAIR.ADMIN_TABLES (
TABLE_NAME => 'REPAIR_TABLE',
TABLE_TYPE => dbms_repair.repair_table,
ACTION => dbms_repair.create_action,
TABLESPACE => 'ETMCDB');
END;
/
 
DECLARE num_corrupt INT;
BEGIN
num_corrupt := 0;
DBMS_REPAIR.CHECK_OBJECT (
SCHEMA_NAME => 'SYS',
OBJECT_NAME => 'T1',
REPAIR_TABLE_NAME => 'REPAIR_TABLE',
corrupt_count => num_corrupt);
DBMS_OUTPUT.PUT_LINE('number corrupt: ' || TO_CHAR (num_corrupt));
END;
/
 
BEGIN
DBMS_REPAIR.SKIP_CORRUPT_BLOCKS (
SCHEMA_NAME => 'SYS',
OBJECT_NAME => 'T1',
OBJECT_TYPE => dbms_repair.table_object,
FLAGS => dbms_repair.SKIP_FLAG);
END;
/
 
SQL> select id from t1;
ID
----------
1
3
4
5
6
7
6 rows selected
 
SQL> select object_name, block_id, corrupt_type, marked_corrupt,corrupt_description,repair_description from repair_table;
OBJECT_NAME BLOCK_ID CORRUPT_TYPE MARKED_CORCORRUPT_DESCRIPTION REPAIR_DESCRIPTION
----------- -------- ------------ ------------------------------ --------------------------
T1 21 6148 TRUE mark block software corrupt
 
SQL> alter system checkpoint;
System altered.
看看这个DBMS_REPAIR“修复”到底做了些什么 

node1*orcl-/u01/app/oracle/product/10.2.0/db_1/bin >bbed parfile=bbed.par

Password:

BBED: Release 2.0.0.0.0 - Limited Production on Wed Nov 17 19:01:05 2010

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

************* !!! For Oracle Internal Use only !!! ***************

BBED> set file 7

FILE# 7

BBED> set block 21

BLOCK# 21

BBED> dump

File: /u02/oradata/ETMCDB02.dbf (7)

Block: 21 Offsets: 0 to 511 Dba:0x01c00015

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

06a20000 1500c001 a8525500 00000102 11000000 01000000 67e60000 a4525500

00000000 02003200 1100c001 0a000300 1e0a0000 87008000 0a061500 01200000

a8525500 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00010100 ffff1400 19080508 05080000 01001908 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

<32 bytes per line>

对比这个数据库没有被破坏时的情况 

BBED> dump

File: /u02/oradata/ETMCDB02.dbf (7)

Block: 21 Offsets: 0 to 511 Dba:0x01c00015

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

06a20000 1500c001 a8525500 00000102 00000000 01000000 67e60000 a4525500


<32 bytes per line>

而这时候查看Block内部,实际上DBMS_REPAIR没有对块做任何的修改只是跳过了该块。实际情况下,checksum坏了往往意味着坏内的数据已经坏了因为我们无法的值正确的Checksum的值,只能跳过。

那么看看RMAN能够对坏块做些什么

首先使用rman检查含有坏块的数据文件:
RMAN> backup validate datafile 7;


随后查看坏块信息v$database_block_corruption
SQL> select * from v$database_block_corruption;

FILE#      BLOCK#     BLOCKS     CORRUPTION_CHANGE# CORRUPTIO

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

7          21         1                           0 FRACTURED


使用rman进行块恢复:
RMAN> blockrecover datafile 7 block 21 from backupset;


如果执行BLOCKRECOVER CORRUPTION LIST会自动按照V$DATABASE_BLOCK_CORRUPTION进行修复
RMAN> BLOCKRECOVER CORRUPTION LIST;


随后确认坏块信息v$database_block_corruption
SQL> select * from v$database_block_corruption;
no rows selected


如果用RMAN备份该文件,而后还原该文件后,则这个坏块的seq_kcbh则被设为0xff。

神器BBED或者DD+UltraEdit

大概说一下如果数据块的损坏应该是offset@18也就是seq_kcbh被标记成0xff。这时检查alert.log如果看到 computed block checksum那么使用BBED其实很容易,进入然后打开损坏的数据块,offset到16,sum apply后oracle会算出正确的checksum值并且写回去。具体算法就是 computed block checksum后边会有一个数值那么转换成二进制和现有的offset 16 17做异或运算就可以算出正确的值。我也是最近才弄明白这种算法,正好复习。

最后还有一种exp+10231事件的终极方法,具体看链接内的eygle的文章。不过对于大表就是个灾难,希望能够在面临这类灾难时有可靠的RMAN备份可用,不然为了几个数据块而去exp..........简直就是侮辱了DBA这个职位。

参考文章

记一次ORA-8103错误的处理
Oracle怎样标记坏块及一次数据恢复 
Oracle中模拟及修复数据块损坏
利用dd修改checksum值的过程
利用BBED修改checksum值的过程
怎样计算出正确的checksum值
http://www.cnblogs.com/buro79xxd/archive/2010/11/22/1884491.html
http://www.itpub.net/thread-991044-1-1.html

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14710393/viewspace-758050/,如需转载,请注明出处,否则将追究法律责任。

下一篇: 用BBED修复坏块
user_pic_default.png
请登录后发表评论 登录
全部评论
<%=items[i].createtime%>

<%=items[i].content%>

<%if(items[i].items.items.length) { %>
<%for(var j=0;j
<%=items[i].items.items[j].createtime%> 回复

<%=items[i].items.items[j].username%>   回复   <%=items[i].items.items[j].tousername%><%=items[i].items.items[j].content%>

<%}%> <%if(items[i].items.total > 5) { %>
还有<%=items[i].items.total-5%>条评论 ) data-count=1 data-flag=true>点击查看
<%}%>
<%}%>
<%}%>

转载于:http://blog.itpub.net/14710393/viewspace-758050/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值