暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

oracle table 段头 block 坏块处理流程

原创 四九年入国军 2024-08-12
113

--1、模拟segment header block 损坏
create table t1
   as
   select * from dba_objects where object_id is not null;
   
alter table t1 add constraint PK_t1 primary key (object_id);


alter system checkpoint;

select count(*) from  scott.t1;
  COUNT(*)
----------
     87336

select header_file,header_block from DBA_SEGments where segment_name='T1' AND OWNER='SCOTT';
HEADER_FILE HEADER_BLOCK
----------- ------------
          4         5522
		  



alter system dump datafile 4 block 5522;
select * from v$diag_info;

----dump block 信息--PAGETABLE SEGMENT HEADER
Block dump from disk:
buffer tsn: 4 rdba: 0x01001592 (4/5522)
scn: 0x0000.00dc4bcd seq: 0x01 flg: 0x04 tail: 0x4bcd2301
frmt: 0x02 chkval: 0xc1fd type: 0x23=PAGETABLE SEGMENT HEADER
Hex dump of block: st=0, typ_found=1



--损坏段头
set dba  4,5522
set offset 8188
d
m /x 0123e491
sum apply 
verify

--重启库后访问表异常

SQL> select count(1) from scott.t1;
select count(1) from scott.t1
                           *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 5522)
ORA-01110: data file 4: '/oradata/orcl/users01.dbf'


select /*+ index(t PK_t1) */  count(rowid) from scott.t1 t;
COUNT(ROWID)
------------
       87336
	   

--基于rowid获取segment header 坏块对象数据  
create table scott.bad_rows (table_name varchar2(60),row_id rowid, oracle_error_code number);
--创建临时表
create  table scott.t1_tmp as select * from t1 where 1=2;


--根据rowid把插入到新表
SET SERVEROUTPUT ON 
DECLARE
 TYPE RowIDTab IS TABLE OF ROWID INDEX BY BINARY_INTEGER;
 CURSOR c1 IS  select /*+index(t PK_t1)*/ rowid from scott.t1 t; --修改地方1
 r RowIDTab;
 rows  NATURAL := 20000;
 bad_rows number := 0 ;
 errors number;
 error_code number;
 myrowid rowid;
BEGIN
 OPEN c1;
 LOOP
   FETCH  c1 BULK COLLECT INTO r LIMIT rows;
   EXIT WHEN r.count=0;
   BEGIN
    FORALL i IN r.FIRST..r.LAST SAVE EXCEPTIONS
     insert into scott.t1_tmp select /*+ ROWID(A) */ * from scott.t1 A where rowid = r(i); --修改地方2
   EXCEPTION
   when OTHERS then
    BEGIN
     errors := SQL%BULK_EXCEPTIONS.COUNT;
     FOR err1 IN 1..errors LOOP
         error_code := SQL%BULK_EXCEPTIONS(err1).ERROR_CODE;
         myrowid := r(SQL%BULK_EXCEPTIONS(err1).ERROR_INDEX);
         bad_rows := bad_rows + 1;
         insert into scott.bad_rows values('scott.t1',myrowid, error_code);  --修改地方3
     END LOOP;
     END;
   END;
  commit;
 END LOOP;
 commit;
 CLOSE c1;
 dbms_output.put_line('Total Bad Rows: '||bad_rows);
END;
/


Total Bad Rows: 0

PL/SQL procedure successfully completed.

select count(1) from scott.t1_tmp;
  COUNT(1)
----------
     87336
---至此数据全部恢复	 
----通过上面pl/sql,基于rowid成功获得segment header 异常对象中的所有数据记录.如果没有主键的表出现该问题,可以参考:使用plsql抢救数据


「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论