ITPub博客

首页 > Linux操作系统 > Linux操作系统 > ORACLE坏块总结2

ORACLE坏块总结2

原创 Linux操作系统 作者:aaqwsh 时间:2011-03-12 09:47:23 0 删除 编辑
五.如何查找坏块所含的数据表名称和数据的rowid
5.1.首先肯定知道那个数据文件坏了,查出该文件的file_id,relative_fno,tablespace_name
 
 利用dba_data_files可以查询file_id(整个数据库唯一序号),RELATIVE_FNO(相对一个表空间内的序号)
 
5.2.找到坏块的ID(可以运行dbverify实现),假设找到的坏块ID为1234。
5.3.运行下面的查询,根据,坏块的file_id,block id查找该块对应的owner,segment_type,
segment_name等信息
 
   select owner,file_id,segment_name, segment_type, block_id, blocks
  from dba_extents
  where file_id=13 and block_id<=1234 and (block_id + blocks- 1) >= 1234;
 
 
5.4.根据坏块的file_id,owner,segment_name,block_id,如果是数据表的话,用下面的查询来得到对应坏块的rowid
 
 假设owner : DAVE
 
     segment_name: BL
 
     file_id    : 13
 
     block_id   : 162
 
 运行下面的查询来获得该块所含的rowid(如果没有索引,可能就不能用下面的方式了):
 
select /*+ index(DAVE, i_test)?*/ rowid
 from DAVE.BL
 where dbms_rowid.rowid_to_absolute_fno(rowid,'DAVE','BL')=13
 and dbms_rowid.rowid_block_number(rowid)=162;  
 
六,如何模拟坏块
 
DBA的基本知识,制造坏块的方法很多的,可以用ultraedit,也可以用dd命令,同时也呆以用orapatch工具
 
6.1 orapatch工具:
$orapatch open tools001.dbf write
patch>set hex --要用十六进制
patch>display 177 --orapatch以512字节为工作模式,假定想破坏第11个block即为:8k/512*11+1(file header)
patch>find 00400003 --选一个要编辑的点
patch>modify 00400002 --破坏
patch>exit
 
6.2用编辑器打开datafile以8192字节为一大小(db的block是8192)
下面是一个block的开始的20个字节和结尾的4个字节
06 02 00 00 08 00 c0 02 6c 43 0d 00 00 00 01 02
00 00 00 00 -- block head
06 02 6c 43 -- block tail这里有scn(6c 43)的情况和block (06)的类型(01)和head的seq: 0x01对应,只要改block尾部的4个字节中的或block开始的对应字节任何一个就一定会有ora-1578,但如果数据库有ora-1578的error不一定是这样引起的
btw:UE不是很好用winhex吧不错喔
 
6.3 BBED工具
 
 
 

七. 如何利用dbms_repair来标记和跳过坏块
但是当数据量很大,或7*24的系统时,我们使用dbms_repair来处理。dbms_repair是从oracle8i开始提供的。
 
准备工作:
createtablespaceblockdatafile'/u01/block.dbf'size5M;
createtableDMMtablespaceblockasselect*fromall_tables;
commit;
CREATEINDEXindx_dmmonDMM(TABLE_NAME);
selectcount(*)fromDMM;
 COUNT(*)
----------
12896
 
 
7.1.创建管理表:
SQL> conn sys/admin as sysdba;
已连接。
SQL> exec DBMS_REPAIR.ADMIN_TABLES('REPAIR_TABLE',1,1,'USERS');
PL/SQL procedure successfully completed
SQL> exec DBMS_REPAIR.ADMIN_TABLES('ORPHAN_TABLE',2,1,'USERS');
PL/SQL procedure successfully completed
 
7.2.检查坏块:dbms_repair.check_object
 
/* Formatted on 2009-12-16 23:41:32 (QP5 v5.115.810.9015) */
Set serveroutput on;
DECLARE
  cc NUMBER;
BEGIN
  DBMS_REPAIR.check_object(schema_name=>'SYS',--注意此处是用户名
                            object_name    =>'DMM',
                            corrupt_count  =>cc);
  DBMS_OUTPUT.put_line(TO_CHAR(cc));
END;
 
正常情况下输入为0.
 
如果有坏块,可以在创建的REPAIR_TABLE中查看块损坏信息:  
 
/* Formatted on 2009-12-17 13:18:19 (QP5 v5.115.810.9015) */
SELECT  object_name,
        relative_file_id,
        block_id,
        marked_corrupt,
        corrupt_description,
        repair_description,
        CHECK_TIMESTAMP
 FROM  repair_table;                                                                                                                                                                                                      
                                                                                                                                          
 
注意:在8i下,check_object只会检查坏块,MARKED_CORRUPT为false,故需要执行第三步:定位坏块,fix_corrupt_blocks定位,修改MARKED_CORRUPT为true,同时更新CHECK_TIMESTAMP。9i以后经过check_object,MARKED_CORRUPT的值已经标识为TRUE了。所以可以直接进行第四步了。
 
 
7.3.定位坏块:dbms_repair.fix_corrupt_blocks    
只有将坏块信息写入定义的REPAIR_TABLE后,才能定位坏块。
/* Formatted on 2009-12-17 13:29:01 (QP5 v5.115.810.9015) */
DECLARE
  cc  NUMBER;
BEGIN
  DBMS_REPAIR.fix_corrupt_blocks(schema_name  =>'SYS',
                                  object_name  =>'DMM',
                                  fix_count    =>cc);
  DBMS_OUTPUT.put_line(a=>TO_CHAR(cc));
END;
 
 
7.4.跳过坏块:
我们前面虽然定位了坏块,但是,如果我们访问table:
SQL> select count(*) fromSYS.DMM;
 
 
ORA-01578: ORACLE数据块损坏(文件号14,块号154)
ORA-01110:数据文件14: 'D: \BLOCK.DBF'
 
还是会得到错误信息。这里需要用skip_corrupt_blocks来跳过坏块:
 
/* Formatted on 2009-12-17 13:30:17 (QP5 v5.115.810.9015) */
execdbms_repair.skip_corrupt_blocks(schema_name=>'SYS',object_name=>'DMM',flags=>1);
 
 
SQL> select count(*) from SYS.DMM;
 
 COUNT(*)
----------
    12850
丢失了12896-12850=46行数据。
 
 
7.5.处理index上的无效键值;dump_orphan_keys
 
/* Formatted on 2009-12-17 13:34:55 (QP5 v5.115.810.9015) */
DECLARE
  cc  NUMBER;
BEGIN
  DBMS_REPAIR.dump_orphan_keys(schema_name        =>'SYS',
                                object_name        =>'INDX_DMM',
                                object_type        =>2,
                                repair_table_name  =>'REPAIR_TABLE',
                                orphan_table_name  =>'ORPHAN_TABLE',
                                key_count          =>CC);
END;
 
通过以下命令可以知道丢失行的信息:
SQL> SELECT * FROM ORPHAN_TABLE;
 
我们根据这个结果来考虑是否需要rebuild index.
7.6.重建freelist:rebuild_freelists
 
/* Formatted on 2009-12-17 13:37:57 (QP5 v5.115.810.9015) */
execdbms_repair.rebuild_freelists(schema_name=>'SYS',object_name=>'DMM');
 
八.设置内部事件使exp跳过坏块
我们可以用设置event的方法来处理坏块:先模拟出坏块,然后用dbv检查,此时,不用dbms_repair,而用下面的方法:
 
8.1.先exp该表试验一下
在这种情况下,如果有备份,需要从备份中恢复,如果没有备份,那么坏块部分的数据肯定要丢失了
在这个时候导出是不允许的:
E:\>exp system/admin file=t.dmp tables=t
 
报错如下:
即将导出指定的表通过常规路径...
. .正在导出表T
EXP-00056:遇到ORACLE错误1578
ORA-01578: ORACLE数据块损坏(文件号4,块号35)
ORA-01110:数据文件4: 'E:\ORACLE\ORADATA\EYGLE\BLOCK.DBF'
导出成功终止,但出现警告。
 
8.2.对于不同的情况需要区别对待,如果损失不是数据而是重要的oracle内部信息,则不能用set event。
 
首先你需要检查损坏的对象,使用以下SQL:
/* Formatted on 2009-12-17 14:00:42 (QP5 v5.115.810.9015) */
SELECT  tablespace_name,
        segment_type,
        owner,
        segment_name
 FROM  dba_extents
 WHERE  file_id=4AND35BETWEENblock_idANDblock_id+blocks-1;
 

 

8.3.如果损失的是数据,ok,可以设置内部事件,使exp跳过这些损坏的block
 
10231事件指定数据库在进行全表扫描时跳过损坏的块
ALTER SYSTEM SET EVENTS='10231 trace name context forever,level 10' ;
然后我们可以导出未损坏的数据
E:\> exp system/admin file=t.dmp tables=t
即将导出指定的表通过常规路径...
. .正在导出表T 8036行被导出
在没有警告的情况下成功终止导出。
然后我们可以drop table,recreate,然后导入数据

8.4.重建表,再导入
SQL> connect sys/admin as sysdba
已连接。
SQL> drop table t;
表已丢弃。
E:\>imp system/admin file=t.dmp tables=t
.正在将system的对象导入到system
. .正在导入表"T" 8036行被导入
成功终止导入,但出现警告。
E:\>exit
SQL> select count(*) from t;
COUNT(*)
----------
8036
 
完成数据恢复.
 
损失的行数可以从2个行数相减计算:
8192 - 8036 = 156行数据
 
 
8.5如果要取消events设置,做以下操作:
1.如果你在初始化参数中设置的
注释之
2.如果在命令行设置的
alter system set events='10231 trace name context off';

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

请登录后发表评论 登录
全部评论

注册时间:2010-11-24

  • 博文量
    132
  • 访问量
    262250