• 다양한 시나리오로 어떻게 리두와 언두가 함께 작동하는지 살펴본다.


  • 언두 테이블스페이스 또는 언두 세그먼트에 저장된 언두 정보는 리두에 의해서도 보호된다.
  • 언두에 대한 변경은 리두를 생성하며 로깅된다.
  • 언두 데이터는 언두 세그먼트에 추가되고 버퍼 캐시에 캐시된다.


INSERT-UPDATE-DELETE 시나리오 예제

  • 다음 문장을 실행할 때 무슨 일이 일어날지 조사한다.

insert into t (x, y) values (1, 1) ;
update t set x = x + 1 where x = 1 ;
delete from t where x = 2 ;


  • 문장 처리 중 시스템이 실패한다면 ?
  • 중간에 ROLLBACK 하면 ?
  • 성공 후 COMMIT 하면 무슨 일이 일어날 것인가 ?


INSERT
  • 리두, 언두 모두 생성.
  • 언두 : INSERT 결과를 원래대로 되돌리는데 필요한 정보를 포함

  • 변경된 언두/인덱스/테이블 블록이 조금씩 캐시되어있다.
  • 각 블록은 리두로그 버퍼에 있는 엔트리에 의해 보호된다.


  • 가설 1 : 시스템이 지금 중단된다.
    • 아무 문제 없음. 재시작 될 때 이 트랜잭션은 원래 없었던 것 처럼 처리된다.


  • 가설 2 : 버퍼 캐시가 현재 가득 찼다.
    • DBWR 이 버퍼캐시 공간 확보를 위해 디스크 플러시 해야하는 상황
    • DBWR 이 LGWR 에 데이터베이스 블록 보호를 위해 리두 엔트리 플러시를 요청
    • LGWR 이 관련 리두 정보를 플러시 한다.
  • 만일 언두 블록과 관련된 리두 엔트리를 플러시하지 않고 테이블 T 의 변경된 블록만 플러시 한 채로 시스템이 실패하면 ?
    • 리두로그 버퍼는 3초마다 플러시 / 버퍼가 ⅓ 이상 차거나 / 버퍼에 저장된 데이터 크기가 1MB 정도 될 경우/커밋 발생시 마다 디스크로 플러시 된다. 어느 시점에라도 리두 버퍼가 플러시될 수 있다.



  • 커밋 하지 않은 채 버퍼캐시에 존재하는 변경 블록이 존재하고, 변경내용을 디스크에 리두한다.


UPDATE
  • INSERT 와 거의 같은 작업을 일으키지만, UPDATE 로 인한 before 이미지 저장 공간이 필요하여 INSERT 보다는 언두 양이 클 것이다.


  • 블록 버퍼 캐시에 좀 더 많은 새로운 언두 세그먼트 블록을 갖고있다.
  • 필요시 UPDATE를 언두하기 위해 테이블/인덱스 블록을 캐시에서 변경함.
  • 좀 더 많은 리두 로그 버퍼 엔트리를 생성했다.
  • INSERT로 인해 생성된 리두로그 일부는 디스크에 있고 일부는 캐시에 있다고 가정한다.


  • 가설 1 : 시스템이 지금 중단된다.
    • 시작 시 오라클은 리두 로그를 읽고 트랜잭션에 대한 리두 로그 엔트리를 찾는다.
    • INSERT 에 대한 리두엔트리는 리두 로그 파일에, UPDATE에 대한 리두는 리두 로그 버퍼에 있는 상태에서 INSERT 를 롤포워드 한다.
    • (Roll forward : 인스턴스 복구 시 리두로그 파일에 기록된 변경내용을 데이터파일에 다시 적용하는 과정)
    • 트랜잭션이 커밋되지 않음을 확인하고, 트랜잭션을 롤백한다.
    • 버퍼 캐시에 방금 롤 포워드 된 언두를 가져와 데이터와 인덱스 블록에 적용하여 INSERT 실행 이전 모습으로 되돌린다.


  • 가설 2 : 애플리케이션이 트랜잭션을 롤백한다.
    • 해당 트랜잭션에 대한 언두 정보를 캐시된 언두 세그먼트 블록에서 찾거나, 플러시된 디스크에서 찾을 것이다.
    • 롤백이 진행될 경우 리두 로그를 사용할 일은 없다.
    • 오라클에서 작업이 정상적으로 진행될 때에는 리두 로그를 읽는 일이 없다.
    • 다른 데이터베이스에서 로그파일을 '트랜잭션 로그' 로만 간주하여 언두와 리두를 분리하지 않는데, 오라클은 분리되어 설계되었다.


DELETE
  • delete 결과로 언두가 생성. 블록은 변경되고 리두는 리두 로그 버퍼로 보내진다.


COMMIT
  • 리두로그 버퍼를 디스크에 플러시한다.


  • 변경된 블록은 버퍼 캐시에 있다. (일부는 디스크에 플러시 되었다.)
  • 트랜잭션을 재현하는데 필요한 모든 리두는 디스크에 있으므로 영속적이다.
  • 이 순간 데이터파일로 부터 직접 데이터를 읽으면, DBWR 이 변경된 블록들을 디스크로 쓰지 않았을 것으로, 트랜잭션이 일어나기 전 모습의 블록을 보게된다.
  • 장애가 발생해도, 리두 로그 파일을 이용해 블록을 최신상태로 만들 수 있기 때문에 상관없다.