모든 오라클 데이타 블럭은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)만약 데이타 딕셔너리의 테이블이나 인덱스에서 손상된 블럭이 발생했다면 지원을 요청해야 한다.