"데이터를 보호하기 위한 안전장치"


1. Redo란?

오라클 DB는 데이터 파일컨트롤 파일에 가해지는 모든 변경사항을 하나의 Redo 로그 엔트리로서 Redo 로그에 기록하게 된다. 

Redo 로그는 크게 두 가지로 구성된다.

  • Online Redo 로그
    : Redo 로그 버퍼에 버퍼링된 로그 엔트리를 기록하는 파일로서, 최소 두 개 이상의 파일로 구성됨.
    - 현재 사용 중인 Redo 로그 파일이 꽉 차면, 다음 Redo 로그 파일로 로그 스위칭이 발생.
     모든 Redo 로그 파일이 꽉 차면 다시 첫 번째 Redo 로그 파일부터 재사용하는 라운드 로빈 방식을 사용.

  • Archived Redo 로그
    : Online Redo 로그가 재사용되기 전에 다른 위치로 백업해 둔 파일.

 

2. Redo 로그의 목적

  1. Database Recovery
    : 물리적으로 디스크가 깨지는 등의 Media Fail 발생 시, 데이터베이스를 복구하기 위해 사용되며, 이때는 Archived Redo 로그를 이용하게 됨.

  2. Cache Recovery
    : Instance Recovery 라고도 함. 버퍼 캐시는 I/O 성능 향상에 매우 효율적이나 휘발성으로 인하여, 캐시에 저장된 변경사항이 디스크 상의 데이터 블록에 아직 기록되지 않은 상태에서 정전 등이 발생하면 인스턴스가 비정상적으로 종료되고, 그때까지의 작업 내용을 모두 잃게 되는데, 이러한 트랜잭션 데이터 유실에 대비하기 위함이다.
    - Instance Crash가 발생되고 시스템을 재기동하면, 우선 Online Redo 로그에 저장된 기록 사항들을 읽어들여 마지막 체크포인트 이후부터 사고 발생 직전까지 수행되었던 트랜잭션들을 재현함.
    - 위와 같은 Roll Forward 과정이 완료되면, Undo 데이터를 이용하여 시스템이 셧다운 되는 시점에 아직 커밋되지 않았던 트랜잭션들을 모두 롤백하는, 'Transaction Recovery' 가 진행됨.

  3. Fast Commit
    : 트랜잭션 발생 시 건건이 데이터 파일(디스크에 위치)에 기록하기보다 우선, 변경사항을 Append 방식으로 빠르게 로그 파일에 기록하고, 메모리 데이터 블록과 데이터 파일 간 동기화는 적절한 수단을 이용하여 나중에 배치(Batch) 방식으로 일괄 수행함으로써, Redo 로그를 믿고 빠르게 커밋을 완료한다는 의미.
    - 오라클에서는 'Delayed 블록 클린아웃' 이라는 추가적인 매커니즘이 작동하는데, 이는 커밋 시점에는 Undo 세그먼트 헤더의 트랜잭션 테이블에만 커밋 정보를 기록하고, *블록 클린아웃은 나중에 수행하도록 하는 것을 말함.

    * 블록 클린아웃 : 갱신된 블록에 커밋 정보를 기록하고 Lock을 해제하는 작업

 

3. Redo 로그의 'Fast Commit' 메커니즘

오라클 DB의 Fast Commit 메커니즘 / 출처 : https://velog.io/@whdnjsdyd111/%EC%98%A4%EB%9D%BC%ED%81%B4-%EA%B3%A0%EB%8F%84%ED%99%94-%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98

Redo 레코드를 기록할 때에도 곧바로 Redo 로그 파일에 저장하는 것이 아니라, 먼저 Redo 로그 버퍼에 기록한다.

Redo 로그 버퍼에 기록된 레코드는 일정 시점마다 LGWR 프로세스에 의해 Redo 로그 파일에 기록된다. (위 그림에서의 3번 과정)

LGWR 가 Redo 로그 버퍼를 Redo 로그에 기록하는 시점은 다음과 같다.

  1. 3초마다 DBWR 프로세스로부터 신호를 받을 때
  2. 로그 버퍼의 3분의 1 이상이 차거나, 기록된 Redo 레코드량이 1MB 이상일 때
  3. 사용자가 커밋 또는 롤백 명령을 내릴 때

또한 위 그림에서의 4번 과정("success code" 리턴)까지 완료되면, 아직 사용자의 갱신내용이 메모리 상의 데이터 버퍼에만 기록된 채 디스크에 기록되지 않았지만, Instance Crash가 발생하더라도 Redo 로그를 이용해 언제든 데이터 복구 가능한 상태가 된다.


1. Undo란?

각 트랜잭션별로 Undo 세그먼트를 할당해 주고, 그 트랜잭션이 발생시킨 테이블과 인덱스에 대한 변경사항들을 Undo 레코드 단위로 Undo 세그먼트 블록에 차곡차곡 기록함.

 

2. Undo의 목적

  1. Transaction Rollback
    : 트랜잭션에 의한 변경사항을 최종 커밋하지 않고, 롤백하고자 할 때 Undo 데이터를 이용.

  2. Transaction Recovery
    : Instance Crash 발생 후, Redo를 이용하여 Roll forward 단계가 완료되면, 최종 커밋되지 않은 변경사항까지 모두 복구됨. 즉, 시스템이 셧다운된 시점에 아직 커밋되지 않았던 트랜잭션들을 모두 롤백해야 하는데, 이때 Undo 세그먼트에 저장된 Undo 데이터를 사용.

  3. Read Consistency (읽기 일관성)
    : DB2, SQL Server, Sybase 등은 Lock을 통해 읽기 일관성을 구현하지만, 오라클은 Undo 데이터를 이용하여 읽기 일관성을 구현.

 

3. Undo 메커니즘의 이해

Undo 세그먼트의 구조 / 출처 : http://wiki.gurubee.net/display/STUDY/Undo%2C.

Undo 세그먼트는 그림에서 보이듯이, 4개의 익스텐트로 이루어져 있다. Initial Extent에는 Undo 세그먼트 헤더(Header) 정보가 담기는데, 이 헤더에는 트랜잭션 테이블 슬롯(Transaction Table Slot)이 위치하며, 각 슬롯에 기록되는 사항들은 아래와 같다.

  • 트랜잭션 ID
    : [USN# + Slot# + Wrap#] 으로 구성되며, USN은 Undo Segment Number의 약자이다. 
  • 트랜잭션 상태 정보(Transaction Status)
    : COMMITTED, ACTIVE와 같은 트랜잭션의 상태를 나타낸다.
  • 커밋 SCN
    : SCN(System Change Number)로서, 데이터베이스의 Commit된 버전을 나타내는 DB 구조라고 볼 수 있다. 트랜잭션이 커밋되면 그 트랜잭션은 트랜잭션 간을 구분시켜주는 SCN을 부여 받는다.
  • Last UBA
    : UBA(Undo Block Address)로서, Undo 레코드 체인을 유지하는 일종의 포인터이다. 

3-1. Undo 세그먼트의 트랜잭션 테이블로부터 슬롯(Slot) 할당

 트랜잭션 ID 구성을 보면 알 수 있듯이, 트랜잭션을 시작하려면 먼저 Undo 세그먼트에 있는 트랜잭션 테이블로부터 슬롯(Slot)을 할당 받아야 하며, 할당받은 슬롯에 자신이 현재 Active 상태임을 표시하고서 갱신을 시작한다.

이때 트랜잭션 슬롯을 곧바로 얻지 못해 이용가능한 슬롯이 생기기를 기다릴 때 발생하는 대기 이벤트 undo segment tx slot 이다.

 

3-2. Undo 블록에 Undo 레코드로서 하나씩 차례대로 기록

 Undo 세그먼트의 트랜잭션 슬롯을 얻은 이후 트랜잭션이 발생시키는 데이터 또는 인덱스 블록에 대한 변경사항 Undo 블록에 Undo 레코드로서 하나씩 차례대로 기록된다.  이때 각 DML 오퍼레이션에 따라 Undo 레코드에 기록되는 내용은 아래와 같다. Undo 블록의 요소에 대한 자세한 내용은 3-4. 에서 살펴보자!

  • Insert : 추가된 레코드의 rowid
  • Update : 변경되는 컬럼에 대한 before image
  • Delete : 지워지는 로우의 모든 컬럼에 대한 before image

하나의 Undo 블록에 쓰기가 완료되면, 새로운 Undo 블록을 할당받아 쓰기 작업을 계속해 나간다.

아래 쿼리를 통해 현재 사용중인 Undo 블록 개수 현재까지 기록한 Undo 레코드 양을 확인할 수 있다.

SELECT s.sid, s.serial#, t.xidusn, t.used_ublk, t.used_urec
FROM v$session s, v$transaction t
WHERE t.addr = s.taddr AND s.sid = 144;

 이때 인덱스가 전혀 없는 테이블이라면, 한 건을 갱신할 때마다 used_urec 값이 하나씩 증가하고,
인덱스가 딸려 있는 테이블이라면, 인덱스 엔트리에 대한 갱신 내용까지 used_urec 값에 포함된다. INSERT 또는 DELETE 연산의 경우 인덱스 하나당 하나의 Undo 레코드가 추가되고, UPDATE 연산의 경우 오라클 내부적으로는 DELETE&INSERT 방식으로 수행되는 것이기 때문에, 인덱스 하나당 2개의 Undo 레코드가 추가된다.

 

3-3. 트랜잭션 상태정보를 'committed'로 변경

사용자가 커밋을 수행하여 트랜잭션이 완료되면, 트랜잭션 상태 정보를 'COMMITTED' 로 변경하고, 해당 시점의 커밋 SCN을 트랜잭션 슬롯에 저장한다. 이후부터는 해당 트랜잭션 슬롯 Undo 블록들 다른 트랜잭션에 의해 재사용될 수 있는데, 가장 먼저 커밋된 트랜잭션 슬롯부터 순차적으로 재사용되기 때문에, 커밋 후 상당 기간이 지난 후에도(커밋이 무수히 많이 일어나지 않았다는 가정하에) Undo 데이터는 남을 수 있게 된다. 참고로, 아직 커밋되지 않은, ACTIVE 상태의 트랜잭션이 사용하는 Undo 블록과 트랜잭션 테이블 슬롯은 절대 다른 트랜잭션에 의해 재사용되지 않는다. 

 

3-4. Undo 블록의 요소

Undo 블록은 '블록 헤더(Block Header)'와 'ITL 슬롯', 'Lock Byte' 로 이루어진다.

Undo 블록 헤더의 구조 / 출처 : http://wiki.gurubee.net/display/STUDY/Undo%2C.

 

3.4.1. ITL(Interested Transaction List) 슬롯

ITL 슬롯에 기록되는 내용은 다음과 같다.

  • ITL 슬롯 번호
  • 트랜잭션 ID
  • UBA (Undo Block Address)
    : 트랜잭션에 의해 발생한 변경 이전 데이터(before image)가 저장된 Undo 블록 주소를 가리키는 포인터.
    CR Copy를 생성하여 과거 버전으로 돌리려고 할 때 사용.
  • 커밋 Flag
  • Locking 정보
  • 커밋 SCN

 특정 블록에 속한 레코드를 갱신하려면, 먼저 블록 헤더로부터 ITL 슬롯을 확보해야 한다. 블록 헤더에 트랜잭션 ID를 기록하고, 현재 해당 트랜잭션이 Active 상태임을 표시한 후부터 블록 갱신이 가능하다.
ITL 슬롯을 할당받지 못하면, 트랜잭션은 계속 진행하지 못하고 블로킹(Blocking) 되었다가, 해당 블록을 갱신하던 앞선 트랜잭션 중 하나가 커밋 또는 롤백될 때 비로소 ITL 슬롯을 얻어 작업을 계속 진행할 수 있게 된다.

 

오라클에서는 ITL 슬롯 부족으로 인한 블로킹 되는 현상을 최소화할 수 있도록, 다음 3가지 옵션을 제공하는데 이는 테이블과 인덱스를 생성할 때 사용하는 파라미터들이다.

  • initrans : 블록을 사용하려고 처음 포맷할 때, 블록 헤더에 ITL 슬롯을 몇 개 할당할 지 결정하는 파라미터
  • maxtrans : 블록 헤더에 미리 할당해 둔 ITL 슬롯이 모두 사용중이라면, 지정된 개수만큼 데이터 영역에 추가 ITL 슬롯을 할당할 수 있도록 하는 파라미터
  • pctfree : 사용 가능한 Block 공간 중 데이터 Row의 UPDATE 등으로 인한 데이터의 변경에 대비하여 확보해 놓은 블록의 % 값을 지정하는 파라미터

 

3.4.2. Lock Byte

: 레코드가 저장되는 로우마다 각 헤더 Lock Byte를 할당하여, 해당 로우를 갱신 중인 트랜잭션의 ITL 슬롯 번호를 기록해 두는데, 이것이 Row level에서의 Lock을 구현하게 한다.

 오라클은 Row level의 Lock과 트랜잭션 level의 Lock(=TX Lock)을 조합하여 Row Lock을 구현하는데, 요컨대, 레코드를 갱신하려고 할 때, 대상 레코드의 Lock Byte가 활성화(Turn-on) 되어 있으면, ITL 슬롯을 찾아가고 다시 그 ITL 슬롯이 가리키는 트랜잭션 테이블 슬롯을 찾아가, 그 트랜잭션이 아직 ACTIVE 상태라면 트랜잭션이 완료될 때까지 대기 (=TX Lock)한다. 다른 DBMS는 Lock 매니저를 통해 현재 갱신 중인 레코드 정보를 관리하는데, 이는 리소스가 유한한 반면, 오라클은 Row level Lock을 별도의 Lock 리소스 사용 없이 레코드의 속성으로서 관리하므로, Lock 에스컬레이션 메커니즘이 전혀 불필요하여 동시성이 현저히 저하되는 것을 막는다.


참조

조시형, 오라클 성능 고도화 원리와 해법 1 

 

https://velog.io/@kw78999/Redo-%EC%99%80-Undo

 

[DB] Redo 와 Undo

데이터파일, 컨트롤 파일에 가해지는 모든 변경사항을 Redo 에 기록한다

velog.io

http://wiki.gurubee.net/display/STUDY/Undo%2C.

 

Undo,. - [종료]구루비 DB 스터디 - 개발자, DBA가 함께 만들어가는 구루비 지식창고!

Undo란? 8i까지는 롤백(rollback)이라는 용어를 사용. 롤백 세그먼트를 생성하고 ONLINE/OFFLINE의 상태변경 등의 작업을 DB관리자가 수동으로 관리했고, rollback_segments 파라미터에 의해 개수 고정. 롤백

wiki.gurubee.net

 

'DB > SQLP 공부' 카테고리의 다른 글

[OracleDB] 오라클DB의 기본 아키텍처  (0) 2022.07.15
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기