모든 오라클 데이타 블럭은sequence   번호(seq)와incarnation 번호(inc)를 갖고 있다. ORA-1578 에러는seq=0 이고inc<>0(새로운 블럭이 아님)일 때 발생한다. ORA-1578 에러는ORA-600[3339] 에러와 함께 발생하곤 한다.

 

ORA-1578 에러가 발생하면 corruption   발생한 화일번호와 블럭번호를 알려준다. 여기서는 이 때의 화일번호를f, 블럭번호를b 라고 부르기로 한다.

 

해결방법

 

1)우선 해야 할 일은   어떠한 오브젝트가corrup 되었는가를 알아내는 것이다.

다음의 스크립트를 이용하면 알 수 있다.

 

SQL>select segment_name, segment_type

from dba_extents

where file_id = f and

b between block_id and block_id + blocks – 1;

 

2)만약 해당 세그먼트가 인덱스이면drop 시키고 다시 생성하면 된다.

 

3)만약 해당 세그먼트가 테이블이면corrup   블럭의 데이타는 손상된 것이다.

 

4)만약 해당 테이블이 들어있는   엑스포트 화일이 있다면 손상된 테이블을drop 시키고 임포트 받는 것이 제일 간단한 방법이다. 하지만 만약 엑스포트 받은 화일이 없거나 백업해둔 화일도 없다면 해당 테이블에 인덱스가 생성되어 있는 경우에 한해서 다음의 방법을 사용해서 복구를 하도록 한다.

 

5)만약 해당 테이블에 대한 인덱스가 생성되어 있다면 이를 이용해서corrup 된 블럭을 피해갈 수 있다. 이 방법은 다음과 같다.

 

– empno, ename, deptno 를 컬럼으로 가지는emp 테이블이corrup되었다고 가정하자. 그리고empno컬럼에 인덱스가 생성되어 있다고 하자.클러스터화되지 않은 모든   테이블은 유니크한rowid를 가진다. rowid를varchar2/hexadecimal 형식으로 표현하려면rowidtochar 함수를 이용한다.

 

SQL>select rowidtochar(rowid) from emp;

 

rowid는 총18자로 블럭어드레스(8자), 점(1자), 로우 어드레스(4자), 점(1자), 화일 어드레스(4자)로 구성되어 있다.

 

SQL>select empno, rowid

from emp

where empno> 0

위의 스크립트를 실행시키면 다음과 같은 결과를 얻게 된다.

 

EMPNO           ROWID

—–           ——

100             00000003.0000.0006

101             00000003.0001.0006

102             00000003.0002.0006

103             00000003.0003.0006

.

.

500             00000004.0000.000A

501             00000004.0001.000A

.

.

755             0000001A.0005.000A

756             0000001A.000C.000A

 

만약 인덱스가character 컬럼에 대한 것이었다면 위의query 문장을 다음과 같이 바꿀 수 있다.

 

SQL>select empno, rowid

from emp

where empno> ”;

 

예를 들어 다음과 같은 에러메시지가 떨어졌다고 하자.

 

01578, 00000, “ORACLE data block corrupted (file # 10, block # 4)

 

그러면 다음의 스크립트를 사용하여   손상된 블럭에 있는employee 에 대한empno를 구할 수 있다.

 

SQL>select empno from emp

where empno> 0

and rowidtochar(rowid) like ‘00000004.%.000A’;

EMPNO           ROWID

—–           —–

500             00000004.0000.000A

501             00000004.0001.000A

 

이제emp 테이블과 같은 구조를 갖는 새로운 테이블을 만든다.

 

SQL>create table temp

as select * from emp

where 1 = 2;

 

그리고는 손상된 부분을 피해서   새로운 테이블에 손상된 테이블의 데이타를 추가한다.

SQL>insert into temp select * from emp where empno < 500;

SQL>insert into temp select * from emp where empno > 501;

손상된 테이블을drop 시키고 temp 테이블의 이름을emp로 변경한다.

그리고 백업된 자료나 문서자료를 통하여 손상된 부분에 대한 정보를 추가한다.

6)손상된 블럭에 여러개의 로우가   존재하고 있다면 다음의 방법을 이용한다.

 

SQL>create table empnos as

select empno from emp

where empno>0

and rowidtochar(rowid) not like ‘00000004.%.000A’;

 

이 스크립트를 이용하면 손상된   블럭에 포함되지 않는empno 들을 알수 있다.

다음의 스크립트를 계속 실행시켜 복구를 한다.

 

SQL>create table temp   as select * from emp where 1 = 2;

SQL>insert into temp

select emp.empno, emp.ename, emp.deptno

from emp, empnos

where emp.empno > 0

and emp.empno = empnos.empno;

 

7)만약 데이타 딕셔너리의 테이블이나 인덱스에서 손상된 블럭이 발생했다면 지원을 요청해야 한다.

By haisins

오라클 DBA 박용석 입니다. haisins@gmail.com 으로 문의 주세요.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다