oracle 新建 逻辑坏块,Oracle数据文件的坏块,可分为物理坏块和逻辑坏块

指的是块内的数据在逻辑是存在问题。比如说索引块的索引值没有按从小到大排列。

物理坏块一般是由于内存问题、OS问题、IO子系统问题和硬件引起,逻辑坏块一般是是由于Oracle Bug等原因引起。

Oracle数据文件的每个块,其块头为20字节。其定义如下:(来自于DSI401)

struct kcbh

{

ub1

type_kcbh;

ub2

frmt_kcbh; ub1

spare1_kcbh;

ub1

spare2_kcbh;

krdba

rdba_kcbh;

ub4

bas_kcbh;

ub2

wrp_kcbh;

ub1

seq_kcbh;

ub1

flg_kcbh; ub2

chkval_kcbh;

};

在块头中,seq_kcbh(占用1字节,块头偏移14)有着特殊的含义,如果该值为0xff,则表示该块被标记为corruption。

下面我们做一个测试:

SQL> create table test.t1 as select * from dba_objects;

表已创建。

SQL> select header_file,header_block from dba_segments where

segment_name=’T1′ and owner=’TEST’;

HEADER_FILE HEADER_BLOCK

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

10 1445

修改db_block_checksum参数值为TRUE,关闭数据库,我们用ultraedit修改10号文件的1447块的check

sum(一个随便>0的数)及flag=0×04。然后再打开数据库。再执行下面的查询:

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

select count(*) from test.t1

*

ERROR 位于第 1 行:

ORA-01578: ORACLE 数据块损坏(文件号10,块号1447)

ORA-01110: 数据文件 10: ‘D:\ORACLE\ORADATA\XJ\TEST01.DBF’

由于非系统表空间在db_block_checksum参数设为FALSE时,会忽略checksum的检查。所以这里为了测试的方便设置为TRUE。

从上面的错误信息来看,块号1447这个块已经坏了,报的错误是经典的ORA-01578错误。

我们用dbv检查一下这个文件:

D:\oracle\oradata\XJ>dbv file=TEST01.dbf blocksize=2048

DBVERIFY: Release 9.2.0.1.0 - Production on 星期一 2月 23 17:20:43

2009

Copyright (c) 1982, 2002, Oracle Corporation. All rights

reserved.

DBVERIFY - 验证正在开始 : FILE = TEST01.dbf

标记为损坏的页1447

***

Corrupt block relative dba: 0×028005a7 (file 10, block

1447)

Bad check value found during dbv:

Data in bad block -

type: 6 format: 2 rdba: 0×028005a7

last change scn: 0×0000.0023b43e seq: 0×2 flg: 0×04

consistency value in tail: 0xb43e0602

check value in block header: 0xf0f0, computed block checksum:

0×3a4f

spare1: 0×0, spare2: 0×0, spare3: 0×0

***

DBVERIFY - 验证完成

检查的页总数 :56660

处理的页总数(数据):53947

失败的页总数(数据):0

处理的页总数(索引):30

失败的页总数(索引):0

处理的页总数(其它):2669

处理的总页数 (段) : 0

失败的总页数 (段) : 0

空的页总数 :13

标记为损坏的总页数:1

汇入的页总数 :0

dbv检查发现了坏块(check错误)。

而如果用analyze命令检查也会发现有坏块:

SQL> analyze table test.t1 validate structure;

analyze table test.t1 validate structure

*

ERROR 位于第 1 行:

ORA-01578: ORACLE 数据块损坏(文件号10,块号1447)

ORA-01110: 数据文件 10: ‘D:\ORACLE\ORADATA\XJ\TEST01.DBF’

我们用dbms_repair来处理这个坏块(实际上如果只是checksum坏了,可以修改checksum为正确的值。但实际情况下,checksum坏了往往意味着坏内的数据已经坏了,大多数情况下只能丢弃):

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 => ’SYSTEM’);

7 end;

8 /

PL/SQL 过程已成功完成。

SQL> set serveroutput on

SQL> declare

2 rpr_count

int;

3 begin

4 rpr_count

:= 0;

5 dbms_repair.check_object (

6 schema_name => ’TEST’,

7 object_name => ’T1′,

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 过程已成功完成。

SQL> select object_name, block_id, corrupt_type,

marked_corrupt,corrupt_description,

2 repair_description from repair_table;

OBJECT_NAME BLOCK_ID CORRUPT_TYPE MARKED_COR

CORRUPT_DESCRIPTION REPAIR_DESCRIPTION

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

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

T1 1447 6148

TRUE mark block software

corrupt

T1 1447 6148

TRUE mark block software

corrupt

SQL> declare

2 fix_count

int;

3 begin

4 fix_count := 0;

5 dbms_repair.fix_corrupt_blocks (

6 schema_name => ’TEST’,

7 object_name => ’T1′,

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 过程已成功完成。

SQL> begin

2 dbms_repair.skip_corrupt_blocks (

3 schema_name => ’TEST’,

4 object_name => ’T1′,

5 object_type => dbms_repair.table_object,

6 flags => dbms_repair.skip_flag);

7 end;

8 /

PL/SQL 过程已成功完成。

SQL> select table_name, skip_corrupt from dba_tables where

table_name = ’T1′ and owner=’TEST’;

TABLE_NAME SKIP_COR

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

T1 ENABLED

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

COUNT(*)

----------

28762

SQL> alter system checkpoint;

系统已更改。

从上面可以看到,dbms_repair.fix_corrupt_blocks并不修复checksum错误,也不做坏块标记。通过dbv和用ultraedit检查块头,没有发现任何变化。但是通过dbms_repair.skip_corrupt_blocks过程在数据字典中将表设置为跳过坏块,则在查询时会跳过该块。

如果用RMAN备份该文件,而后还原该文件后,则这个坏块的seq_kcbh则被设为0xff。而此时用dbv检查该文件则显示的错误信息则为:

DBVERIFY - 验证正在开始 : FILE = TEST01.dbf

DBV-00200: 块, dba 41944487, 已经标记为崩溃

DBVERIFY - 验证完成

检查的页总数 :56655

处理的页总数(数据):53948

失败的页总数(数据):0

处理的页总数(索引):30

失败的页总数(索引):0

处理的页总数(其它):2669

处理的总页数 (段) : 0

失败的总页数 (段) : 0

空的页总数 :8

标记为损坏的总页数:0

汇入的页总数 :0

注意这里“标记为损坏的总页数”跟前一次检查的不一样,这里为“0”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值