1. 버퍼캐시와 OWI
1) 버퍼 캐시 구조
오라클은 물리적인 I/O 를 최소화하기 위해 최근에 사용된 블록에 대한 정보를 메모리의 일정 영역에 보관한다.
이 메모리 영역을 버퍼 캐시라고 부른다.
버퍼 캐시는 Shared Pool, 리두 버퍼와 함께 SGA 를 이루는 가장 중요한 메모리 영역 중 하나이다.
SQL> show sga
오라클은 버퍼 캐시를 효과적으로 관리하기 위해 해시 체인 구조를 사용한다.
해시 체인은 Shared Pool 내에 존재하며 오라클의 전형적인 메모리 구조 관리기법인
버킷 (Bucket) → 체인 (Chain) → 헤더 (Header) 의 구조를 사용한다.
해시 체인 구조의 시작점은 해시 테이블이다.
해시 테이블은 여러 개의 해시 버킷으로 이루어져 있다.
하나의 해시 버킷은 해시 함수 결과와 매칭된다.
오라클은 블록의 주소 (DBA) 와 블록 클래스에 대해 간단한 해시 함수를 적용한 결과를 이용해 해시 버킷을 찾아간다.
해시 버킷에는 같은 해시 값을 갖는 버퍼 헤더 들이 체인 형태로 걸려 있다.
버퍼 헤더는 버퍼에 대한 메타 정보를 가지고 있으며,
버퍼 메모리 영역의 실제 버퍼에 대한 포인터 값을 가지고 있다.
해시 체인 구조는 Shared Pool 영역에 존재하며,
실제 버퍼에 대한 정보들은 버퍼 캐시 영역에 존재한다는 사실을 명심하자.
해시 체인 구조는 cache buffer chains 래치를 이용해 보호된다.
특정 블록을 스캔하고자 하는 프로세스는 반드시 해당 블록이 위치한 해시 체인을 관리하는 cache buffers chains 래치를 획득해야 한다.
기본적으로 한번에 하나의 프로세스만이 하나의 cache buffers chains 래치를 획득할 수 있으며
하나의 cache buffer chains 래치가 여러 개의 해시 체인을 관리한다.
따라서 동시에 많은 수의 프로세스가 버퍼 캐시를 탐색할 경우 cache buffer chains 래치를 획득하는 과정에서 경합이 발생하며,
이 과정에서 latch: cache buffers chains 이벤트를 대기한다.
오라클 9i 부터는 읽기 전용의 작업에 한해서 cache buffers chains 래치를 Shared 모드로 획득한다.
따라서 동시에 읽기 작업을 수행하는 프로세스 간에는 cache buffers chains 래치를 공유할 수 있다.
하지만 버퍼에 대해 buffer lock 을 획득하거나 해제할 때 cache buffers chains 래치를 Exclusive 하게 획득해야 하기 때문에
읽기 작업만 수행하는 경우에도 여전히 cache buffers chains 래치 경합은 발생한다.
2) Working Set
LRU 리스트 (대체 리스트)
- 메인 리스트: 사용된 버퍼들의 리스트, 핫 영역과 콜드 영역으로 구분 관리
- 보조 리스트: 프리 버퍼들의 리스트, 미 사용된 버퍼들이나 DBWR 에 의해 기록된 버퍼들의 리스트
LRUW 리스트 (기록 리스트)
- 메인 리스트: 변경된 버퍼들의 리스트
- 보조 리스트: 현재 DBWR에 의해 기록중인 버퍼들의 리스트
오라클은 프리 버퍼 탐색시, 우선 LRU 리스트의 보조 리스트에서 프리 버퍼를 찾는다.
보조 리스트의 버퍼가 모두 사용된 경우에는, 메인 리스트의 콜드 영역에서 프리 버퍼를 찾는다.
LRU, LRUW 리스트는 항상 짝 (Pair) 으로 존재하며, 이 짝을 Working Set 이라고 부른다.
오라클은 복수개의 Working Set 을 사용한다.
하나의 Working Set 을 하나의 cache buffer lru chain 래치가 관리한다.
반드시 래치를 획득해야 한다.
동시에 많은 프로세스가 리스트를 탐색하고자 할 때 latch:cache buffers lru chain 이벤트를 대기한다.
서버 프로세스가 스캔하는 모든 버퍼들이 LRU 리스트에 등록되기 때문에 LRU 리스트를 효율적으로 관리하는 것이 매우 중요하다.
8i 이후 버전부터 Touch count 에 기반한 LRU 알고리즘을 사용한다. LRU 리스트의 메인 리스트를 관리하는 데 사용된다.
3) Buffer lock
cache buffers chains 래치와 cache buffers lru chain 래치가
해시 체인 구조와 Working Set 구조를 보호하는 역할을 한다면
Buffer Lock 은 버퍼 자체를 보호하는 역할을 한다.
4) 버퍼 탐색
오라클은 해시 체인과 LRU, LRUW 리스트를 적절히 사용해서 사용자가 요청한 블록을 버퍼 캐시로 위치시킨다.
그 절차 및 기법을 시간순으로 정리하면 다음과 같다.
1. 사용자가 요청한 블록의 DBA 와 클래스에 대해 해시 함수를 이용해서 해시 값을 생성하고 해시 값에 해당하는 해시 버킷 값을 찾는다.
2. 해시 버킷을 보호하는 cache buffer chains 래치를 획득한다.
읽기 작업이라면 Shared 모드,
변경 작업이라면 Exclusive 모드로 래치를 획득한다.
만일 이 과정에서 경합이 발생하면 latch: cache buffers chains 이벤트를 대기한다.
해시 버킷에 딸려있는 체인을 탐색해서 블록에 해당하는 버퍼 헤더가 존재하는지 확인한다.
버퍼 헤더가 이미 존재하고 해당 블록이 버퍼 캐시에 올라와 있는 상태라면
해당 버퍼에 대해 buffer lock 을 Shared 모드나 Exclusive 모드로 획득하고 원하는 작업을 수행한다.
일반적으로 buffer lock 을 획득하는 과정에서 경합이 발생하면
buffer busy waits 이벤트를 대기하게 된다.
DBWR에 의해 기록중인 버퍼에 대해 buffer lock 을 획득하는 과정에서 경합이 발생하는 경우에는
write complete waits 이벤트를 대기한다.
cache buffers chain 래치를 획득한 후 버퍼를 읽는 일련의 작업을 "Logical Reads" 라고 부른다.
Logical Reads 가 발생한 블록 수만큼 session logical reads 통계 값이 증가한다.
만일 Logical Reads 작업이 일관된 모드의 읽기 (Consistent read) 작업이라면 consistent gets 통계 값이 증가하고,
현재 모드의 읽기 (Current read) 작업이라면 db block gets 통계 값이 증가한다.
따라서 session logical reads 통계 값은 consistent gets 통계값과 db block gets 통계 값의 합과 일치한다.
3. 버퍼 캐시에 블록이 존재하지 않으면 우선 Working Set 을 관리하는 cache buffers lru chain 래치를 획득한다.
이 과정에서 경합이 발생하면 latch: cache buffers lru chain 이벤트를 대기한다.
래치를 획득한 후 LRU 리스트의 보조 리스트에서 프리 버퍼를 찾는다.
이 과정에서 더티 버퍼가 발견되면 LRUW 리스트로 이동시킨다.
프리 버퍼를 찾게 되면 해당 버퍼에 대해 buffer lock 을 Exclusive 하게 획득하고 데이터 파일로부터 블록을 해당 버퍼로 읽어 들인다.
이 때 buffer lock 을 획득하는 과정에서 경합이 발생하면 read by other session 이벤트를 대기한다.
데이터 파일로부터 물리적으로 블록을 읽어 들이는 일련의 작업을 "Physical Reads" 라고 부른다.
Physical Reads 가 발생한 블록 수만큼 physical reads 통계값이 증가한다.
physical reads 통계 값은 direct path I/O 작업에서도 증가하기 때문에,
버퍼 캐시를 경유한 정확한 Physical Reads 값은 physical reads 통계 값에서 physical reads direct, physical reads direct (lob) 통계 값을 빼면 된다.
4. LRU 리스트에서 프리 버퍼를 찾을 때 _DB_BLOCK_SCAN_MAX_PCT (기본값은 40) 파라미터의 값만큼 스캔을 하고도 프리버퍼를 찾지 못하면
서버 프로세스는 LRU 리스트의 스캔을 멈춘다.
서버 프로세스는 DBWR 에게 더티 버퍼를 파일에 기록하고 프리 버퍼를 확보할 것을 요청한다.
DBWR 에 의해 프리 버퍼가 확보될 때까지 서버 프로세스는 free buffer waits 이벤트를 대기한다.
요청을 받은 DBWR 은 DBWR make free request 통계값을 증가시키고,
cache buffers lru chain 래치를 획득한 후 LRUW 리스트를 콜드 영역의 꼬리에서부터 탐색한다.
디스크에 기록할 버퍼를 찾게 되면 buffer lock 을 획득한 후 버퍼를 디스크에 기록한다.
디스크에 기록된 버퍼는 프리 버퍼로 변경되고 LRU 리스트로 옮겨진다.
DBWR 이 LRUW 리스트를 탐색할 때마다 DBWR lru scans 통계 값과 DBWR buffers scanned 통계 값이 증가한다.
Logical Reads 의 엄격한 정의는
"블록을 보관하고 있는 버퍼 영역을 찾아가기 위해 버퍼가 속한 해시 버킷을 관리하는 cache buffers chains 래치를 획득하고,
해시 체인 리스트를 탐색한 후, 메모리 I/O 를 통해 원하는 블록이미지를 얻어오는 작업" 이다.
오라클은 과다한 체인 탐색에 의한 래치 경합을 줄이기 위해 Buffer Pinning 이라는 기법을 사용한다.
특정 세션의 동일 SQL 콜내에서 2번 이상 스캔된 버퍼는 Pinned 상태로 변환된다.
Pinned 상태란 래치를 획득하지 않고도 곧바로 버퍼영역에 갈 수 있도록 버퍼의 위치를 저장하고 있다는 의미이다.
Pinned 상태의 버퍼는 버퍼 캐시에서 밀려나지 않기 때문에 저장된 위치를 이용해 래치 없이 곧바로 찾아갈 수 있다.
Pinned 상태의 버퍼를 탐색할 경우에는 session logical reads 통계값 대신 buffer is pinned count 통계값이 증가한다.
Pinned 상태의 버퍼라고 하더라도 메모리 I/O 자체는 발생하며, 대신 래치 획득과 해시 체인 탐색과 같은 부가적인 작업이 줄어든다는 것에 주의하자.
5) 버퍼 캐시 덤프
버퍼의 구조를 가장 명확하게 알 수 있는 방법은 버퍼 캐시 덤프를 이용하는 것이다.
2. Shared Pool / Library Cache 와 OWI
1) Shared Pool 과 Heap
Shared Pool 은 SGA 영역 중
Variable 영역에 속한다.
Variable 영역은 Shared Pool + Java Pool + Large Pool + Streams Pool 등으로 이루어진다.
Shared Pool 은 다시 여러 종류의 메모리 영역으로 나누어진다.
대표적인 것들이 Library Cache 와 Row Cache 이다.
Shared Pool 이 어떤 메모리 영역으로 나누어지는 V$SGASTAT 뷰를 아래와 같이 조회함으로 확인 가능
Shared Pool 구성 요소
- Permanent Area: process, session, segmented array (enqueue, transaction, ..) 등. 프로세스 목록, 세션 목록, Enqueue 목록, Transaction 목록 등의 자원은
Shared Pool 의 영구 영역 (Permanent Area) 에 할당되며 인스턴스와 그 수명을 같이 한다.
- Library Cache: SQL 문을 수행하는데 필요한 모든 객체 (SQL, 테이블, 뷰, 프로시저 등) 에 대한 정보를 관리한다.
- Row Cache: Dictionary Cache 라고도 부르며, 오라클이 사용하는 딕셔너리 정보를 관리한다.
- Reserved Area: 예약 영역, 동적인 메모리 할당을 위해 오라클의 여분의 예약 영역을 할당해둔다.
shared pool 래치는 기본적으로 전체 인스턴스에 하나만 존재하며, 필요한 메모리(청크)를 할당받는 전체 과정동안 보유해야 한다.
따라서 동시에 많은 프로세스가 Shared Pool 메모리를 사용하는 경우 래치를 획득하는 과정에서 경합이 발생하게 된다.
9i 이상부터는 shared pool 을 여러개의 서브풀로 최대 7개까지 나누어서 관리할 수 있다.
2) Library Cache 구조
Library Cache 영역은 SQL 문의 수행과 관련된 모든 정보들을 관리하는 영역이다.
Library Cache 메모리는 해시테이블 → 버킷 → 체인 → 핸들 → 오브젝트의 구조로 되어 있다.
LCO 가 포함하는 정보 중 중요한 것들은
- Dependency Table
- Child Table
- Data Blocks
3) SQL 수행
1. 사용자가 새로운 SQL 문장을 수행 요청하면 오라클은 기본적인 문법체크와 권한체크 등을 수행한 후,
해시 버킷을 관리하는 library cache 래치를 획득하고,
library cache 영역에 동일한 SQL 문장, 즉 동일한 LCO 가 존재하는지 확인한다.
library cache 래치를 획득하는 과정에서 경합이 발생하면 latch:library cache 이벤트를 대기한다.
동일한 LCO 가 존재하는 경우에는 8번 단계를 실행하게 되는데, 이 과정을 소프트 파싱 (Soft Parsing) 이라고 부른다.
오라클은 SQL 파싱 요청이 있을 때마다 parse count (total) 통계값을 증가시킨다.
2. 만일 동일한 SQL 문장이 존재하지 않는다면, shared pool 래치를 획득하고 가장 적절한 크기의 프리 청크를 프리리스트에서 찾는다.
shared pool 래치를 획득하는 과정에서 경합이 발생하면 latch: shared pool 이벤트를 대기한다.
오라클은 프리 청크가 확보될 때까지 계속해서 shared pool 래치를 보유한다.
3. 만일 최적 크기의 프리 청크가 존재하지 않으면 조금 더 큰 크기의 프리 청크를 찾아서
이를 쪼개어 (Split) 사용한다. 쪼개고 남은 메모리 영역은 다시 적절한 프리리스트로 등록된다.
4. 모든 프리리스트를 탐색하고도 적절한 크기의 프리 청크를 찾지 못하면 LRU 리스트를 탐색한다.
LRU 리스트의 청크들은 재생성가능 (Recreatable) 하면서 현재 사용중이지 않은 것 (pin되지 않은 것)들이다.
5. LRU 리스트를 탐색하고도 적절한 크기의 청크를 확보하지 못하면 Shared Pool 내의 여유메모리 공간을 추가적으로 할당한다.
6. 위 과정이 모두 실패하면 ORA-4031 에러가 발생한다.
7. 적절한 프리 청크를 찾으면 SQL 문장에 해당하는 핸들 (Library Cache Handle) 에 대해 library cache lock 을
Exclusive 하게 획득하고 LCO 정보를 생성한다.
LCO 가 생성되면 library cache lock 을 Null 모드로 변환하고, library cache pin 을
Exclusive 하게 획득한 후 실행 계획 (Execution Plan) 을 생성한다.
2번 - 7번까지의 과정을 하드 파싱 (Hard Parsing) 이라고 부른다.
하드 파싱이 발생하면 오라클은 parse count (hard) 통계값을 증가시킨다.
만일 하드파싱 과정에서 SQL 문장의 오류가 발견되면 (가령 존재하지 않는 객체 참조 등)
parse count (hard) 통계값과 함께 parse count (failure) 통계값이 증가한다.
8. 오라클은 SQL 커서에 대해 library cache lock 과 library cache pin 을 Shared 모드로 획득하고 SQL 문장을 실행한다.
이 과정을 실행 (Execute) 단계라고 부른다. SQL 커서가 참조하는 LCO (테이블, 프로시저 등) 에 대해서는 기본적으로 SQL 커서와 동일한 모드로
library cache lock 과 library cache pin 을 획득한다.
하지만 DDL 문장과 같이 객체 정보를 변경하는 작업을 수행하는 경우에는 해당 객체에 해당하는 LCO 에 대해서
library cache lock 과 library cache pin 을 Exclusive 모드로 획득하기도 한다.
예를 들어 "alter table xxx and varchar2(10)" 과 같은 SQL 문장이 수행되는 경우
수행 (Execute) 단계에서 SQL 커서 자체에 대해서는 library cache lock 을 Shared 모드로 획득하지만,
테이블 xxx 에 해당하는 LCO 에 대해서는 library cache lock 을 Exclusive 모드로 획득한다.
libarary cache lock 과 library cache pin 을 획득하는 과정에서 경합이 발생하면
각각 library cache lock 이벤트와 library cache pin 이벤트를 대기한다.
9. 오라클은 실행이 완료된 SQL 커서에 대해 데이터를 페치한다. 이 과정을 페치 (Fetch) 단계라고 부른다.
패치 단계에서는 SQL 커서에 대해 library cache lock 을 Null 모드로 변환하고 library cache pin 은 해제한다.
오라클 매뉴얼에서는 Null 모드로 획득한 library cache lock 을 breakable parse lock 이라고 부른다.
3. 트랜잭션과 OWI
1) 트랜잭션 개요
트랜잭션을 완벽하게 이해한다는 것은 오라클을 완벽하게 이해한다는 것과 같은 의미를 지닌다.
사용자가 DML 수행 (트랜잭션 수행)
1. 해당 트랜잭션에 대해 언두 세그먼트 할당
온라인 언두 세그먼트 우선, 다른 트랜잭션이 사용 중이라면 3번까지 재시도
실패하면 오프라인 언두 세그먼트를 온라인화 해서 사용
실패하면 새로운 언두 세그먼스 생성
실패하면 롤백 세그먼트 알고리즘 사용, 이미 다른 트랜잭션에 의해 사용 중인 언두 세그먼트 중 가장 사용량이 적은 것을 사용
2. 언두 세그먼트 헤더에 트랜잭션 테이블 슬롯 (transaction table slot) 생성
3. TXID 생성, 현재 트랜잭션에 할당
트랜잭션은 반드시 언두 영역을 할당받은 다음에 ID를 부여받는다.
4. 트랜잭션의 대상이 되는 블록들을 버퍼 캐시로 적재하고 블록 헤더의
ITL (Interested Transaction List) 에 트랜잭션 엔트리 (Transaction Entry) 를 등록한다.
만일 ITL 에 엔트리를 등록할 공간이 없다면, 공간이 확보될 때까지
enq:TX-allocate ITL entry 이벤트를 대기한다.
5. 변경할 블록들의 변경 정보는 PGA 에 체인지 벡터라는 이름으로 저장된다.
보통 하나의 로우가 변경되는 경우 각각 언두 헤더 블록 (체인지 벡터#1), 언두 블록 (체인지 벡터#2),
데이터 블록(체인지 벡터#3) 에 해당하는 체인지 벡터들이 생긴다.
프로세스는 PGA 체인지 벡터들을 리두 레코드 (또는 리두 엔트리) 라는 이름으로 리두 버퍼 (Redo Buffer) 로 복사한다.
리두 버퍼에 변경 내용을 복사하는 과정에서
redo copy 래치, redo allocation 래치, redo writing 래치를 획득해야 한다.
이 과정에서 래치 경합이 발생하면 각각 latch: redo copy, latch: redo allocation, latch: redo writing 이벤트를 대기한다.
6. 이전 이미지 (Before Image) 에 대한 정보를 언두 블록에 기록하고, 데이터 블록을 변경한다.
변경된 데이터 블록은 더티 (Dirty) 상태가 된다.
또한 변경된 데이터 블록에 대한 CR 블록이 버퍼 캐시에 생성된다.
만일 변경하고자 하는 로우가 현재 다른 트랜잭션에 의해 변경 중 (즉 변경 후 아직 트랜잭션이 종료되지 않은 상태) 라면
해당 트랜잭션이 종료되기를 기다려야 하며 enq: TX - row lock contention 이벤트를 대기한다.
7. 커밋이 수행되면, 트랜잭션에 SCN 을 할당한다. 커밋 정보는 리두 버퍼에 저장된다.
8. 언두 세그먼트 헤더의 트랜잭션 테이블에 커밋이 이루어졌음을 저장하고, 락을 포함한 모든 리소스에 대한 점유를 해제한다.
9. 리두 버퍼의 내용이 리두 로그 파일에 기록된다. 변경된 블록들은 이후 DBWR 에 의해 데이터 파일로 기록된다.
2) 트랜잭션과 블록 덤프
3) 트랜잭션과 언두 헤더 덤프
4. 세그먼트와 OWI
1) 세그먼트 개요
오라클은 세그먼트라는 개념을 이용해 데이터베이스 공간을 관리한다.
세그먼트는 테이블, 인덱스, 언두, LOB 등 오라클이 제공하는 모든 종류의 논리적인 공간을 말한다.
HWM 은 세그먼트 헤드 블록에 그 정보가 저장된다.
HWM 은 세그먼트 전체 공간 중 사용가능 공간 (포맷된 공간) 과 미사용 공간 (미 포맷 공간) 을 구분하는 기준이 된다.
HWM 을 이동하는 작업은 HW 락을 통해 보호된다.
2) FLM (Freelist Management) - 수동 세그먼트 공간 관리
PCTFREE=10, PCTUSED=40
블록 내에 데이터가 90% 이하까지 사용된 경우에는 프리 블록 상태이다.
Delete 나 Update 에 의해 데이터가 줄어드는 경우 40% 이하로 떨어지면 다시 프리 블록 상태가 된다.
오라클은 세그먼트 별로 기본적으로 하나의 마스터 프리리스트를 할당하며
세그먼트 생성시 FREELISTS 속성 값에 할당된 수만큼 프로세스 프리리스트를 사용한다.
3) ASSM (Automatic Segment Space Managemnet) - 자동 모드의 세그먼트 공간 관리
9i 부터는 자동화된 공간 관리가 가능해졌다.
ASSM 을 사용하면 프리리스트 속성을 지정할 필요가 없으며 각 블록의 상태를 비트맵 값으로 관리하는 비트맵 블록들에 의해 공간관리가 자동화 된다.
모든 블록의 여유 공간 정보가 비트맵 블록에서 관리되기 때문에 FLM 에서와 같은 프리리스트 구조를 사용하지 않는다.
또한 PCTUSED 속성은 더 이상 사용되지 않는다. 하지만 PCTFREE 속성은 여전히 사용된다.
5. I/O 와 OWI
1) I/O 개요
1. 어플리케이션 레이어 : select/insert/update/delete/truncate...
2. 오라클 메모리 레이어: Buffer cache | PGA
3. 오라클 세그먼트 레이어: Datafile, tempfile, Tablespace, Segment
4. OS/디바이스 레이어: Asynch I/O, Direct I/O, Raw device, RAID, ...
2) 어플리케이션 레이어 (Application Layer)
어플리케이션을 효과적으로 구현하여 불필요한 I/O 를 최소화해야 한다.
3) 오라클 메모리 레이어 (Oracle Memory Layer)
오라클이 제공하는 기능
첫째, Touch count 기반의 효율적인 LRU 알고리즘을 제공한다.
둘째, Buffer Pinning 기법을 통해 불필요한 래치 경합을 줄이고, 현재의 읽기 작업에 사용될 확률이 높은 블록들을 메모리에서 밀려나지 않게끔 한다.
셋째, 다중 버퍼 풀 (Multiple buffer pool) 기능을 이용하면 휘발성 블록과 메모리 상주 블록을 구분해서 효과적으로 관리할 수 있다.
넷째, 오라클 9i 부터는 블록 크기를 2K ~ 32K 까지 사용가능하다.
다섯째, 메모리에 올릴 필요가 없는 대용량의 데이터를 처리할 때는 버퍼 캐시를 우회하는 방법을 사용할 수 있다.
4) 오라클 세그먼트 레이어 (Oracle Segment Layer)
일반적인 데이터들은 데이터파일에 저장된다. 임시 테이블 스페이스를 사용할 경우, 기본적으로 데이터 파일이 아닌 임시파일에 데이터를 저장한다.
5) O/S 디바이스 레이어 (Device Layer)
컨트롤 파일의 개수나 리두 로그 파일의 개수가 불필요하게 많다면 복구가 가능한 최소한만큼만 유지하는 것도 도움이 된다.
한가지 유념할 것은 로디바이스나 Direct I/O 가 비효율적으로 과다하게 I/O 를 수행하는 어플리케이션에 대한 무조건적인 해결책이 아니라는 사실이다.
6) Direct path I/O
버퍼 캐시를 우회하는 I/O 작업을 direct path I/O 라고 부른다.
6. 리두와 OWI
1) 리두 개요
리두 데이터를 생성하는 이유는 복구를 위한 것
Write ahead rule: 데이터를 변경시키기 전에 반드시 리두를 먼저 생성
Log force at commit: 사용자가 커밋을 요청하면, 반드시 관련된 모든 리두 레코드를 리두 로그 파일에 저장해야만 커밋이 종료된다는 의미이다.
테이블을 Nologging 옵션으로 생성했다고 하더라도 단순 Insert, Update, Delete 에 대해서는 반드시 리두가 생성된다.
2) 리두 버퍼 (Redo Buffer)
데이터를 변경하려는 모든 프로세스는 반드시 리두 버퍼에 변동사항을 기록한다.
1. 데이터 변동사항을 프로세스 메모리 영역 (PGA) 에 체인지 벡터 (Change Vector) 로 저장한다.
2. 현재 자신의 SCN 이 모든 프로세스가 지닌 SCN 중 가장 높은 SCN 인지 확인한다.
3. redo allocation 래치를 획득한 후, 리두 버퍼 내에 리두 레코드를 저장할 공간을 확보한다.
4. PGA 에 생성한 체인지 벡터를 리두 레코드 형태로 리두 버퍼로 복사한다.
_LOG_PARALLELISM 히든 파라미터 값을 이용해서 redo strands 의 개수를 지정할 수 있다.
오라클은 CPU개수/8 정도의 값을 사용할 것을 권장한다.
10g 부터 리두 버퍼를 관리하는 기법 개선
1. shared redo strands 개수 지정
2. private redo strands 기능 도입
3) 리두 로그 (Redo log)
리두 로그 파일은 리두 로그 블록 단위로 기록된다.