오라클은 데이터 파일과 컨트롤 파일에 가해지는 모든 변경사항을 하나의 Redo 로그 엔트리로서 Redo 로그에 기록한다. Redo 로그는 Online Redo 로그와 Offline(Archived) Redo 로그로 구성된다.
Online Redo 로그는 로그 버퍼에 버퍼링된 로그 파일이 꽉 차면 다음 Redo 로그 파일로 로그 스위칭이 발생하며, 계속 Redo 로그를 써 나가다가 모든 Redo 로그 파일이 꽉 차면 다시 첫 번째 Redo 로그 파일부터 재사용하는 라운드 로빈 방식을 사용한다.
Archived Redo 로그는 Online Redo 로그가 재사용되기 전에 다른 위치로 백업해 둔 파일을 말한다.
Redo 로그의 목적?
Database Recovery
첫째, Redo 로그는 물리적으로 디스크가 깨지는 등의 Media Fail 발생 시 데이터 베이스를 복구하기 위해 사용되며, 이때는 Archived Redo 로그를 이용하게 된다. 'Media Recovery'라고도 부른다.
Cache Recovery
둘째, Redo 로그는 Cache Recovery를 위해 사용되며 다른 말로 'Instance Recovery'라고도 한다. 모든 데이터베이스 시스템이 버퍼 캐시를 도입하는 것은 I/O 성능을 향상시키기 위함이지만, 따라서 캐시에 저장된 변경사항이 디스크 상의 데이터 블록에 아직 기록되지 않은 상태에서 정전 등이 발생해 인스턴스가 비정상적으로 종료되면, 그때까지의 작업 내용을 모두 잃게 된다. 이러한 트랜잭션 데이터의 유실에 대비하기 위해 Redo 로그를 사용한다.
Fast Commit
마지막으로, Redo 로그는 Fast Commit을 위해 사용된다. 변경된 메모리 버퍼 블록을 디스크 상의 데이터 블록에 기록하는 작업은 Random 액세스 방식으로 이루어지기 때문에 굉장히 느리다. 반면 로그는 Append 방식으로 기록하므로 매우 빠르다. 따라서 트랜잭션 발생 시 건건이 데이터 파일에 기록하기보다 우선 변경사랑을 Append 방식으로 빠르게 로그 파일에 기록하고 메모리 데이터 블록과 데이터 파일 간 동기화는 적절한 수단을 이용해 나중에 배치 방식으로 수행한다.
사용자의 갱신내용이 메모리상의 버퍼 블록에만 기록된 채 아직 디스크에 기록되지 않았지만 Redo 로그를 믿고 빠르게 커밋을 완료한다는 의미에서, 이른 매커니즘을 'Fast Commit' 이라고 부른다. 적어도 커밋 정보가 로그에 기록돼 있기만 하다면 인스턴스 Crash가 발생하더라도 Redo 로그를 이용해 언제든 Recovery가 가능한 상태가 되므로 오라클은 안심하고 커밋을 완료할 수 있는 것이다.
Delayed 블록 클린아웃이란 ?
Fast Commit은 오라클에만 있는 기능이 아니며, 빠른 트랜잭션을 처리하는 모든 DBMS의 공통적인 메커니즘이다. 그런데 Fast Commit을 구현하는 데 있어 오라클만의 특징적인 기능이 있는데, 그것이 바로 'Delayed 블록 클린아웃'이다. 완전한 커밋을 위해서는 Lock을 해제하는 일까지 완료해야 하는데, 다른 DBMS는 Lock 매니저를 통해 로우 Lock을 관리하기 때문에 커밋 시점에 빠르게 Lock 리소스를 해제할 수 있다.
반면 오라클은 별도의 Lock 매니저 없이 레코드의 속성으로서 로우 Lock을 구현했기 때문에 Lock을 해제하려면 갱신했던 블록들을 일일이 찾아다녀야 한다. 그래서 오라클은 'Delayed 블록 클린아웃'이라는 추가적인 메커니즘을 사용해, 커밋 시점에는 Undo 세그먼트 헤더의 트랜잭션 테이블에만 커밋 정보를 기록하고, 블록 클린아웃은 나중에 수행하도록 한다.
LGWR가 Redo 로그 버퍼를 Redo 로그에 기록하는 시점
Redo 레코드를 기록할 때도 곧바로 Redo 로그 파일에 저장하는 것은 아니며 먼저 Redo 로그 버퍼에 기록한다. 즉, 데이터 블록 버퍼를 변경하기 전에 항상 Redo 로그 버퍼에 먼저 기록하고 일정 시점마다 LGWR 프로세스에 의해 Redo 로그 버퍼에 있는 내용을 Redo 로그 파일에 기록하는 것이다.
1번에서 DBWR가 Dirty 버퍼를 데이터파일에 기록하기 전에 로그 버퍼를 먼저 Redo로그에 기록하도록 하는 이유는 뭘까?
Instance Crash 발생 시 Redo 로그에 기록된 내용을 재현해 캐시 블록을 복구하고 최종적으로 커밋되지 않은 트랜잭션은 롤백하게 되는데, Redo 로그에는 없는 변경내역이 이미 데이터 파일에 기록돼 있으면 사용자가 최종 커밋하지 않은 트랜잭션이 커밋되는 결과를 초래하기 때문이다.
정리해보면, 버퍼 캐시에 있는 블록 버퍼를 갱신하기 전에 먼저 Redo 엔트리를 로그 버퍼에 기록해야 하며, DBWR가 버퍼 캐시로부터 Dirty 블록들을 디스크에 기록하기 전에 먼저 LGWR가 해당 Redo 엔트리를 모두 Redo 로그 파일에 기록했음이 보장되어야 한다. 이를 "Write Ahead Logging" 이라고 한다.
과거에는 롤백이라는 용어를 주로 사용했지만, 9i부터 오라클에서는 Undo라는 용어를 사용하고 있다. AUM(Auto Undo Managemant)이 도입되어 Undo 세그먼트마다 하나의 트랜잭션이 할당되는 것을 목표로 세그먼트 개수를 오라클이 자동 관리한다. 트랜잭션에 독립적으로 할당해 줄 Undo 세그먼트가 없을 때는 가장 적게 사용되는 Undo 세그먼트 중 하나를 골라 할당한다. 또한 AUM에서는 다른 Undo 세그먼트로부터 Free Undo Space를 가져올 수 있으며, Undo 테이블 스페이스 내에 있는 모든 Undo Space를 소진했을 때 비로소 에러를 발생시킨다.
Undo의 목적 ?
Transaction Rollback
첫째, 트랜잭션에 의해 변경사항을 최종 커밋하지 않고 롤백하고자 할 때 Undo 데이터를 이용한다.
Transaction Recovery
둘째, Redo에서 Instance Crash 발생 후 Redo를 이용해 Roll forward 단계가 완료되면 최종 커밋되지 않은 변경사항까지 모두 복구된다. 따라서 시스템이 셧다운된 시점에 아직 커밋되지 않았던 트랜잭션들을 모두 롤백해야 하는데, 이때 Undo 세그먼트에 저장된 Undo 데이터를 사용한다.
Read Consistency
마지막으로, 오라클은 Lock이 아닌 Undo 데이터를 이용해 읽기 일관성을 구현한다.
(1) Undo 세그먼트 트랜잭션 테이블 슬롯

Undo 세그먼트 중 첫 번째 익스텐트, 그중에서도 첫 번째 블록에는 Undo 세그먼트 헤더정보가 담긴다.
1. Transaction ID
2. Transaction Status
트랜잭션 시작
트랜잭션 완료(사용자가 커밋)
3. Last UBA
- 아직 커밋되지 않은, Active 상태의 트랜잭션이 사용하는 Undo 블록과 트랜잭션 테이블은 절대 다른 트랙잭션에 의해 재사용되지 않는다.
- 트랜잭션이 완료돼 사용자가 커밋한 Commited상태의 트랜잭션은 다른 트랜잭션에 의해 재사용 가능하다.
'트랜잭션이 완료됐어도 지정한 시간동안은 "가급적" Undo 데이터를 재사용하지 말라'라고 오라클에 힌트를 주는 것
강제성을 갖지 않기 때문에 expired Extent가 없고 새로 할당할 공간까지 부족해지면 unexpired 상태의 Extent라도 언제든 재사용할 수 있다.
- retention guarantee 기능
- Automatic Undo Retention Tuning 기능
(2) 블록 헤더 ITL 슬롯

ITL 슬롯의 정보들
오라클은 ITL 슬롯 부족 때문에 트랜잭션이 블로킹 되는 현상을 최소화할 수 있도록 3가지 옵션을 제공
- inittrans 파라미터
-> 블록을 사용하려고 처음 포맷할 때 블록 헤더에 ITL 슬롯을 몇 개 할당할지를 결정하는 파라미터- maxtrans 파라미터
-> 블록 헤더에 미리 할당해 둔 ITL 슬롯이 모두 사용 중이라면 maxtrans로 지정된 개수만큼 데이터 영역에 추가 ITL 슬롯을 할당- pctfree 파라미터
(3) Lock Byte
오라클은 레코드가 저장되는 로우마다 그 헤더에 Lock Byte를 할당해 해당 로우를 갱신 중인 트랜잭션의 ITL 슬롯 번호를 기록해 둔다. 이것이 로우 단위 Lock이며, 오라클은 로우 단위 Lock과 트랜잭션을 조합해 로우 Lock을 구현한다.