坏块的处理与恢复

Eygle 2019-07-24
19
0 0
摘要:坏块的处理与恢复

有时候为了学习测试,我们常常希望能够模拟数据块损坏,然后来研究相应问题的处理方法,最常见的是使用第三方软件进行数据块修改,模拟数据块损坏。以下是一种常见的模拟及坏块问题的解决方法及步骤。

首先构造测试数据,创建相应的表空间等:

SQL> create tablespace block datafile 'e:\oracle\oradata\eygle\block.dbf' size 1M;

表空间已创建。

变更测试用户使用该表空间:

SQL> alter user eygle default tablespace block;

用户已更改。

SQL> alter user eygle quota unlimited on block;

用户已更改。

创建测试表及构造测试数据:

SQL> connect eygle/eygle
已连接。
SQL> create table t as select * from dba_tables;
表已创建。
SQL> insert into t select * from t;
已创建4096行。
SQL> /
insert into t select * from t
*
ERROR 位于第 1 行:
ORA-01653: 表EYGLE.T无法通过8(在表空间BLOCK中)扩展
SQL> commit;
提交完成。

关闭数据库后可以用Ultredit等工具编辑数据文件,选择特定的数据部分,更改或者删除一些字符,然后启动数据库(有时候你可能需要多次更改才能成功损坏数据块),此时查询测试表,发现数据块已经损坏:

SQL> select count(*) from eygle.t;
select count(*) from eygle.t
*
ERROR 位于第 1 行:
ORA-01578: ORACLE 数据块损坏(文件号4,块号35)
ORA-01110: 数据文件 4: 'E:\ORACLE\ORADATA\EYGLE\BLOCK.DBF'
使用DBV检查数据文件,可以检测到块损坏:
E:\Oracle\oradata\eygle>dbv file=block.dbf blocksize=8192
 
DBVERIFY - 验证正在开始 : FILE = block.dbf
标记为损坏的页35
***
Corrupt block relative dba: 0x01000023 (file 4, block 35)
Bad check value found during dbv:
Data in bad block -
type: 6 format: 2 rdba: 0x01000023
last change scn: 0x0000.00049097 seq: 0x1 flg: 0x06
consistency value in tail: 0x90970601
check value in block header: 0xd6cb, computed block checksum: 0x2c0a
spare1: 0x0, spare2: 0x0, spare3: 0x0
***

在这种情况下,如果有备份,需要从备份中恢复;如果没有备份,那么坏块部分的数据肯定要丢失了,在这个时候导出是不允许的:

E:\>exp eygle/eygle file=t.dmp tables=t
即将导出指定的表通过常规路径 ...
. . 正在导出表 T
EXP-00056: 遇到 ORACLE 错误 1578
ORA-01578: ORACLE 数据块损坏(文件号4,块号35)
ORA-01110: 数据文件 4: 'E:\ORACLE\ORADATA\EYGLE\BLOCK.DBF'
导出成功终止,但出现警告。

当然,对于不同的情况需要区别对待,首先你需要检查损坏的对象,使用以下SQL:

SQL> SELECT tablespace_name, segment_type, owner, segment_name FROM dba_extents
2  WHERE file_id = 4 and 35 between block_id AND block_id + blocks - 1;
TABLESPACE_NAME  SEGMENT_TYPE     OWNER      SEGMENT_NAME
---------------- ---------------- ---------- ---------------
BLOCK             TABLE           EYGLE      T

如果损失的是数据(如果是索引块损坏,通常可以通过索引重建来解决),我们可以设置内部事件,使exp跳过这些损坏的block:

SQL> ALTER SYSTEM SET EVENTS='10231 trace name context forever,level 10';

系统已更改。

然后可以导出未损坏的数据

E:\>exp eygle/eygle file=t.dmp tables=t

即将导出指定的表通过常规路径 ...

. . 正在导出表 T 8036 行被导出

在没有警告的情况下成功终止导出。

这时候数据成功导出,此后可以通过drop table,重建数据表导入数据。本例中我们损失了8192 - 8036 = 156 行数据。

除了使用这种方式之外,还可以使用Oracle提供的dbms_repair包进行坏块标记,从而可以使查询跳过这些坏块,减少坏块对于表扫描访问的影响。


「喜欢文章,快来给作者赞赏墨值吧」

评论

0
0
Oracle
订阅
欢迎订阅Oracle频道,订阅之后可以获取最新资讯和更新通知。
墨值排行
今日本周综合
热门文章
近期活动
全部
相关课程
全部