Skip to content

13화 · 파고들기 ​

필요할 때 찾아보는 문서다. 처음 읽을 때는 1_사건.md만으로 충분하다. 이 문서의 숫자는 모두 실측값이다. ora-hanorder(12화 종료 상태)의 복사본(_C13)에서 쟀고, 실습 스크립트 번호를 함께 적었다. redo 바이트나 죽는 행 번호 같은 값은 실행할 때마다 조금씩 흔들린다. 그래서 판정은 '몇 배인가, 어떤 에러인가, 몇 줄인가'로 한다.

찾는 것바로 가기
변경 벡터 → redo 레코드 → redo strand · WAL · Fast Commit§1 redo
COMMIT은 무엇을 쓰나 · dirty는 왜 남나§2 commit
Undo의 3층: 트랜잭션 테이블 슬롯 · ITL · 행 lock byte§3 undo 3층
블록 클린아웃 · 지연 클린아웃 · 01화 5,842의 정체§4 클린아웃
CR 블록 생성 단계 (읽기 일관성)§4.5 CR
ORA-01555의 원인 3종 · fetch across commit§5 01555
ORA-30036 vs ORA-01555: 반대쪽 두 장애§6 30036
커밋 주기: 무엇이 비싸지나 · log file sync§7 커밋주기
반쯤 반영 (쪼갠 배치의 중간 실패)§8 반쯤반영
IMU (In-Memory Undo)§9 IMU
측정값 전부§10 측정
Free에서 못 잰 것§11 한계
원천 좌표§12 좌표

1. redo — 변경 벡터 · WAL · Fast Commit ​

데이터를 바꾸는 작업은 모두 바꾸기 전에 그 변경을 로그에 먼저 적는다. 이것이 WAL(Write-Ahead Logging)이다. 일지가 먼저, 장부는 나중이다.

  • 변경 벡터(change vector): "이 블록의 이 자리를 이렇게 바꿔라"를 담은 한 조각이다. DML 하나는 보통 변경 벡터를 두 개 이상 만든다. 데이터 블록을 바꾸는 벡터와, 그 되돌림 정보(undo)를 언두 블록에 적는 벡터다.
  • redo 레코드(redo record): 원자적 변경 하나에 속한 변경 벡터들을 묶은 것이다. undo 블록을 바꾸는 것도 redo로 보호된다. 언두 자체도 복구 대상이기 때문이다.
  • 로그 버퍼 → redo strand → 로그 파일: redo 레코드는 SGA의 로그 버퍼(이 컨테이너의 log_buffer는 약 4MB)에 모였다가 LGWR가 온라인 리두 로그 파일로 내려보낸다. 여러 세션이 동시에 redo를 만들면 로그 버퍼를 여러 가닥(redo strand)으로 나눠 경합을 줄인다.

실측 — 한 행 UPDATE (실습/02 [A]) ​

무엇값
redo entries5
redo size약 2,272바이트
undo change vector size약 464바이트
db block changes약 11

한 행을 고쳤는데 undo 변경 벡터도 함께 생긴다. 바꾼 값(redo)과 바꾸기 전 값(undo)을 동시에 적기 때문이다.

Fast Commit — 커밋이 빠른 이유 ​

COMMIT은 바뀐 데이터 블록을 디스크에 쓰지 않는다. 그 트랜잭션의 redo를 로그 파일까지 밀어내고(flush), 언두 세그먼트 헤더의 트랜잭션 테이블 슬롯에 커밋 SCN을 적으면 끝난다. 쓰는 양이 작으니 빠르다. 이것을 Fast Commit이라고 한다.


2. COMMIT은 무엇을 쓰나 ​

실측 — COMMIT 하나 (실습/02 [B]) ​

무엇값
redo entries약 2 (커밋 레코드)
redo size약 1,212바이트
undo change vector size약 172
log file sync+1

COMMIT 뒤에도 dirty가 남는다 (실습/02 [C] · ← 07화) ​

단계그 객체의 dirty 버퍼
CREATE TABLE … AS SELECT 직후4 (헤더)
UPDATE + COMMIT 뒤31

07화에서 넘겨받은 바로 그 31이다. COMMIT은 데이터 블록을 디스크에 쓰지 않는다. 그래도 안전한 이유는 두 가지다.

  • 바꾼 내용은 이미 redo(일지)로 디스크에 적혀 있다(WAL). 인스턴스가 죽어도 redo를 다시 적용(roll forward)해 블록을 되살린다.
  • 데이터 블록을 디스크로 내려보내는 것은 DBWn의 일이다. 체크포인트가 걸릴 때(또는 버퍼가 필요할 때) 비동기로 처리하므로 커밋과는 따로 움직인다.

그래서 "커밋했으니 디스크에 저장됐다"는 말은 틀렸다. 커밋이 보장하는 것은 redo가 디스크에 있다는 사실이지, 데이터 블록이 디스크에 있다는 것이 아니다.


3. Undo의 3층 — 트랜잭션 테이블 슬롯 · ITL · 행 lock byte ​

트랜잭션이 행을 잠그고 되돌리는 데 필요한 정보는 세 층으로 나뉘어 서로를 가리킨다. 12화에서 TX 이름표만 보고 넘어간 부분의 속 내용이다.

① 언두 세그먼트 헤더의 트랜잭션 테이블 슬롯  (트랜잭션 하나당 한 칸)
     usn / slot / wrap = 12화의 TX 이름표.  상태(활성/커밋) · 커밋 SCN · 언두 시작 주소
        ▲ 가리킴
② 블록 머리의 ITL (Interested Transaction List) 칸  (이 블록을 건드리는 트랜잭션 목록)
     Xid(위 슬롯을 가리킴) · Uba(이 변경의 언두 블록 주소) · Flag · Lck(잠근 행 수)
        ▲ 가리킴
③ 행 머리의 lock byte  (이 행이 이 블록의 ITL 몇 번 칸에 묶였나)

실측 — 블록 덤프로 ITL Flag 읽기 (실습/06 [B] · SYSDBA) ​

행 하나를 고치고 커밋하기 전에 블록을 덤프하면 다음과 같다.

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0005.018.0000099a  0x00009bee.011d.0a  C---    0  scn  0x0000000000639338
0x02   0x0004.016.000007f8  0x00009d18.0187.31  --U-    1  fsc  0x0000.00639346

커밋한 뒤 다시 덤프하면 그 칸의 Flag가 --U- → C---로 바뀌고 커밋 SCN이 적힌다.

읽을 것뜻이 덤프
Xid트랜잭션 이름표. usn.slot.wrap(16진수)0x0004.016.000007f8 = usn 4 · slot 22 · wrap 2040 (12화의 그 이름표)
UbaUndo Block Address. 이 변경의 되돌림 슬립이 있는 언두 블록0x00009d18.0187.31
Flag--U- 활성(미커밋) · C--- 커밋됨 · ---- 빈 칸둘째 칸이 --U- → 커밋 후 C---
Lck이 ITL 칸이 이 블록에서 잠근 행 수1 (한 행을 고쳤다)
Scn/Fsc커밋이면 커밋 SCN · 활성이면 Fsc(free space credit)—

꺼내는 법(트레이스는 컨테이너 안에 있다. Git Bash에서는 MSYS_NO_PATHCONV=1을 붙인다): docker exec ora-hanorder bash -c "grep -n -A3 'Itl' <Default Trace File 경로>" 경로는 덤프 직후 SELECT value FROM v$diag_info WHERE name='Default Trace File';로 확인한다.

그래서 락 에스컬레이션이 없다 (← 12화 §11) ​

행 락은 블록 안(행의 lock byte → ITL 칸)에 적힌다. 락 관리자 메모리에 행마다 적히는 것이 아니다. 10만 행을 잠가도 락 관리자가 아는 것은 트랜잭션 하나(슬롯 하나)뿐이라서 테이블 락으로 올릴 이유가 없다(12화 실측: 10만 행 UPDATE 뒤에도 V$LOCK은 2줄). 대신 대가가 있다. 블록마다 ITL 칸이 필요하고(ITL 부족 → 12화 §10), 그 표시를 나중에 누군가 지워야 한다(블록 클린아웃 → §4).


4. 블록 클린아웃 · 지연 클린아웃 ​

트랜잭션이 커밋하면 그 트랜잭션이 건드린 블록들의 ITL에 커밋 SCN을 적어 'ITL을 닫아야' 한다. 이것이 블록 클린아웃이다.

종류언제비용
commit cleanout (즉시)커밋 시점에 블록이 아직 버퍼 캐시에 있으면 그 자리에서 닫는다커밋이 흡수한다
지연 클린아웃 (delayed)블록이 너무 많거나(캐시의 약 10% 초과) 커밋 전에 캐시에서 밀려나면 '열린 ITL'을 단 채 디스크로 간다. 다음에 그 블록을 읽는 세션이 닫는다읽기가 redo를 쓴다

실측 — 지연 클린아웃 (실습/06 [A] · SYSDBA) ​

큰 UPDATE를 하고, 커밋하기 전에 그 블록들을 캐시에서 내보낸 뒤(실험에서는 FLUSH BUFFER_CACHE로 흉내 냈다) 커밋했다. 그다음 같은 SELECT를 두 번 돌렸다.

첫 읽기둘째 읽기
redo size152,888바이트2,076
cleanouts only - consistent read gets1,6940
immediate (CR) block cleanout applications1,6940
consistent gets3,4311,739

읽기만 했는데 첫 SELECT가 redo를 15만 바이트 쓰고 블록 1,694개를 청소했다. 둘째 SELECT는 깨끗하다. 밤 배치가 돈 다음 날 아침에 첫 조회가 유난히 느린 현상이 바로 이것이다.

01화 "설치 직후 첫 실행 5,842"의 정체 — 재측정 (설계와 달랐다) ​

개정계획에는 이 추가분이 "지연 클린아웃일 수 있다"고 적혀 있었다. 재 보니 아니었다.

  • T_ORD_BIG은 INSERT /*+ APPEND */(직접 경로)로 적재한다. 직접 경로로 쓴 블록은 깨끗한 상태로 기록되므로 지연 클린아웃이 남지 않는다. 실제로 첫 읽기와 둘째 읽기의 consistent gets가 같았다(약 5,830).
  • 따라서 5,842 → 5,827의 추가분은 지연 클린아웃이 아니다. 첫 실행 때 드는 하드 파싱과 재귀 조회(딕셔너리, 동적 샘플링) 오버헤드다.
  • 규칙 3 함정표의 'cold cache 첫 실행이 몇 블록 적게 찍힌다'(5,827→5,822)와도 다른 현상이다. 한쪽은 캐시가 차가워서 적게 찍히고, 다른 쪽은 첫 파싱이라 많이 찍힌다.

교훈: 가설이 '지연 클린아웃'이었더라도 직접 경로 적재는 지연 클린아웃을 남기지 않는다. 측정 결과가 설계와 다르면 측정을 따른다.


4.5 CR 블록 — 읽기 일관성이 만드는 사본 ​

쿼리는 시작한 시점(스냅샷 SCN)의 데이터를 봐야 한다(읽기 일관성). 그 사이에 누군가 블록을 바꿔 커밋했다면, 오라클은 현재 블록(CURRENT)을 복사하고 그 사본에 언두를 적용해 스냅샷 시점으로 되돌린 CR 블록(Consistent Read 블록)을 만든다.

CR 블록 만드는 단계
 1. 현재 블록을 버퍼 캐시에 복사한다 (→ 'CR blocks created')
 2. 블록 ITL 을 보고, 스냅샷 SCN 이후에 커밋/활성인 변경을 찾는다
 3. 그 변경의 Uba 로 언두 블록을 찾아, 되돌림을 적용한다 (→ 'data blocks consistent reads - undo records applied')
 4. 스냅샷 SCN 시점의 모습이 될 때까지 2~3 반복
  • 07화에서 본 V$BH.status = 'cr' 사본이 바로 이것이다.
  • 3번 단계에서 필요한 언두 블록이 이미 재사용돼 사라졌다면 ORA-01555가 난다(§5).
  • 지연 클린아웃된 블록을 읽을 때도 ITL을 되살리려고 언두를 보는데, 그 언두가 없으면 역시 01555가 난다.

5. ORA-01555의 원인 3종 ​

ORA-01555 "snapshot too old"는 읽기 일관성에 필요한 과거 언두가 이미 사라졌다는 뜻이다. 언두가 사라지는 경로는 세 가지다.

#원인무엇이이 화에서
1롤백 세그먼트(언두)를 덮어씀긴 쿼리가 도는 동안 다른 트랜잭션(또는 자기 자신)이 커밋하면서, 그 쿼리가 써야 할 언두를 재사용해 덮어썼다실습/04 실측 (에러 메시지의 rollback segment … too small)
2트랜잭션 테이블 슬롯 재사용CR 블록을 만들려면 "그 트랜잭션이 언제 커밋됐나"를 언두 세그먼트 헤더의 슬롯에서 봐야 하는데, 그 슬롯이 다른 트랜잭션에 재사용돼 과거 정보가 사라졌다개념 (작은 언두·많은 트랜잭션에서 발생)
3지연 클린아웃 중지연 클린아웃된 블록을 읽으며 "그 트랜잭션이 커밋됐나"를 확인하려는데, 그 트랜잭션의 슬롯/언두가 이미 사라져 커밋 시점을 구하지 못한다§4의 연장

fetch across commit — 왜 자기 발등을 찍나 ​

sql
FOR r IN (SELECT ... FROM T ORDER BY ...) LOOP   -- 긴 커서: 스냅샷 SCN 은 OPEN 시점
  UPDATE T SET ... WHERE ...;                      -- 읽는 그 테이블을 고치고
  IF MOD(n,N)=0 THEN COMMIT; END IF;               -- 커밋 → 방금 쓴 언두를 '재사용 가능'으로 푼다
END LOOP;

커서의 스냅샷은 OPEN 시점에 고정된다. 그런데 루프가 그 테이블을 고치고 커밋하면, 커서가 나중에 읽을 블록의 과거 언두가 그 커밋 때문에 풀려 버린다. 커서가 그 블록에 닿아 CR 블록을 만들려고 할 때 언두가 없으면 ORA-01555가 난다. 읽는 사람과 지우는 사람이 같은 셈이다.

실측 — 두 가지 모양 (실습/04) ​

모양어떻게 재나결과
동시 커밋이 과거를 지운다긴 읽기 커서(정렬 없이 흘려 읽기) + 그 사이 다른 세션이 같은 테이블을 계속 UPDATE·COMMIT긴 읽기가 약 200행째에서 ORA-01555 (두 번 모두 재현)
자기 커밋이 과거를 지운다인덱스 순서로 읽으며 행을 고치고 커밋 (단일 세션)이 버전, 이 데이터에서는 잘 안 난다(아래 주의 참고)

⚠️ 단일 세션에서 스스로 발등을 찍는 경우(self-inflicted)는 이 버전에서 재현이 들쭉날쭉했다. 한빛유통 정산 데이터는 CUS_ID(= MOD(SEQ,2000))가 물리 순서와 상관돼 있어서, 인덱스 순서로 읽어도 같은 블록을 다시 만나는 간격이 좁았다. 그래서 언두가 아직 남아 있는 경우가 많았다. 교재에서 확실하게 재현할 때는 두 세션의 동시 커밋을 쓴다. 긴 읽기를 돌리는 동안 다른 세션이 그 테이블을 고치는 방식이다. 커밋이 긴 읽기의 과거를 지운다는 메커니즘은 같다. → §11

그래서 처방은 커밋 주기가 아니라 '읽기와 쓰기 분리'다. 목록을 먼저 담고 커서를 닫은 뒤 쓰거나, 키 범위로 쪼개 조각마다 자기 스냅샷을 갖게 하거나, 집합 연산(14화)으로 바꾼다. 커밋 간격을 늘려도 긴 커서가 열려 있는 한 과거는 계속 풀린다.


6. ORA-30036 vs ORA-01555 — 반대쪽 두 장애 ​

ORA-30036ORA-01555
메시지unable to extend segment … in undo tablespacesnapshot too old: rollback segment too small
모자란 것지금 쓸 언두 공간 (활성 트랜잭션이 다 쥠)과거 시점의 언두 (이미 재사용됨)
피해자지금 쓰는 트랜잭션오래 읽는 커서/쿼리
커밋을 덜 하면가까워진다멀어진다
커밋을 더 하면멀어진다가까워진다
언두를 늘리면풀린다안 풀린다 (사라진 과거는 안 돌아온다) · retention을 늘려야 한다
한 줄"되돌릴 공간이 없다""되돌릴 과거가 없어졌다"

실측 — 같은 작은 언두(6M)에서 (실습/03 · 04) ​

배치커밋결과
보정 배치 [A]한 번만ORA-30036 · 약 42,000행째 (강도현 2020.07 재현)
보정 배치 [B]1,000건마다 + 긴 읽기 동시ORA-01555 · 약 200행째

커밋 주기 하나만으로는 두 벽 사이를 빠져나갈 수 없다. 한쪽 벽(30036)을 피하려고 커밋을 당기면 다른 벽(01555)에 붙는다. 길은 읽기와 쓰기를 떼어 내는 것뿐이다. ORA-01555가 'retention' 문제라면 UNDO_RETENTION이나 RETENTION GUARANTEE로 미룰 수는 있지만, fetch across commit 구조는 그대로 남는다.


7. 커밋 주기 — 무엇이 비싸지나 ​

실측 — P1 적재 10만 건, 커밋 주기만 바꿔서 (실습/01) ​

한 번(once)1,000건매 건1,000건 + WRITE WAIT
user commits3102100,002102
redo size약 3,000만약 3,000만약 5,700만약 3,000만
redo entries약 103,000약 102,000약 147,000약 102,000
undo change vector size약 680만약 680만약 1,360만약 680만
session logical reads약 110,000약 110,000약 373,000약 110,000
log file sync (내 세션)222101
LGWR log file parallel write약 50약 120약 650약 115

이 표에서 읽을 것:

  • 한 번 ≈ 1,000건. redo와 undo가 거의 같다. 덩어리가 너무 작지만 않으면 끊는 비용은 거의 보이지 않는다.
  • 매 건 커밋은 과하다. redo 약 1.9배, undo 약 2배, 논리 읽기 약 3.4배, LGWR 기록 약 13배다. 커밋할 때마다 커밋 레코드 redo와 블록 변경이 늘고, 로그도 더 자주 내려보낸다.
  • log file sync의 함정. PL/SQL 루프 안의 COMMIT에서는 세션이 매번 기다리지 않는다. 10만 번 커밋해도 log file sync는 2회였다. 대신 LGWR의 log file parallel write가 는다(50→650). 그런데 COMMIT WRITE WAIT를 쓰면(또는 클라이언트가 건마다 커밋하면) 커밋마다 log file sync를 기다린다(101). 행 단위로 커밋하는 애플리케이션이 느린 진짜 이유가 이것이다.

log file sync와 log file parallel write는 짝이다: 앞의 것은 커밋한 세션이 'LGWR가 내 redo를 다 썼나'를 기다린 시간이고, 뒤의 것은 LGWR가 실제로 디스크에 쓴 시간이다. log file sync가 크면 LGWR 쪽(I/O, CPU)을 살펴보거나 커밋 횟수를 줄인다(V$SESSION_EVENT / V$SYSTEM_EVENT).


8. 반쯤 반영 — 원자성의 대가 ​

실측 — 같은 배치가 50,000행째에서 장애 (실습/07) ​

커밋반영된 건그대로인 건
한 번만0100,000
1,000건마다50,00050,000
  • 한 번 커밋은 원자적이다. 중간에 죽으면 ROLLBACK이 전부 되돌린다(전부 아니면 전무).
  • 쪼갠 커밋은 중간에 죽으면 이미 커밋한 만큼 남는다(반쯤 반영). 다시 돌리면 그 부분을 또 처리할 수 있다(이중 보정).
  • 쪼갤 거라면 재시작 지점을 설계한다. 어디까지 했는지 적어 두고(체크포인트 테이블), 다시 돌릴 때 멱등하게 처리하거나 이미 한 부분은 건너뛰게 짠다. → 「정합성 회귀 체크리스트」 E(경계: 반쯤 반영)·H(영향: 재실행).

9. IMU — In-Memory Undo ​

이 인스턴스는 IMU가 켜져 있다(_in_memory_undo = TRUE). IMU는 작은 트랜잭션의 언두와 redo를 공유 풀의 전용 메모리 풀에 잠깐 모았다가, 커밋하거나 플러시할 때 언두 세그먼트와 로그 버퍼로 한꺼번에 내보낸다. 그만큼 라치를 잡는 횟수와 redo를 기록하는 횟수가 준다.

  • 흔적은 V$SYSSTAT의 IMU commits, IMU Flushes, IMU undo allocation size에서 볼 수 있다.
  • 실측에서는 매 건 커밋 쪽의 IMU commits가 크게 잡혔다. 작은 커밋이 IMU 경로를 많이 탔다는 뜻이다.
  • IMU가 있으면 단일 세션 self-inflicted ORA-01555를 재현하기가 더 어렵다. 언두를 메모리에 더 오래 쥐고 있어서 과거가 덜 사라지기 때문이다. → §5 주의 · §11

10. 이 화의 측정값 전부 ​

커밋 주기 (실습/01 · P1 적재 10만 건) ​

지표once1000each1000+WAIT
user commits3102100,002102
redo size~3,002만~3,001만~5,717만~3,002만
undo change vector size~680.9만~681.4만~1,362만~681.4만
session logical reads~110,221~110,509~373,014~110,658
log file sync (세션)222101
LGWR log file parallel write~50~120~650~115

변경 벡터 · 커밋 · dirty (실습/02) ​

무엇값
한 행 UPDATEredo entries 5 · undo change vector 약 464바이트 · db block changes 약 11
COMMIT 하나redo 약 1,212바이트 · undo 약 172 · log file sync +1
dirty: CTAS 직후 → UPDATE+COMMIT 뒤4 → 31 (← 07화)

ORA-30036 / ORA-01555 (실습/03 · 04 · 작은 언두 6M · retention 1) ​

무엇값
한 번 커밋 배치ORA-30036 · 약 42,000행째
긴 읽기 + 동시 커밋ORA-01555 · 약 200행째 (2회 재현 동일)
원복 확인undo_tablespace UNDOTBS1 · undo_retention 900 · UNDO_C13 삭제

지연 클린아웃 · ITL (실습/06 · SYSDBA) ​

무엇값
지연 클린아웃 첫 읽기 vs 둘째redo 152,888 → 2,076바이트 · cleanouts 1,694 → 0
ITL Flag--U-(활성·Lck 1) → C---(커밋·SCN) · ----(빈 칸)
ITL Xid0x0004.016.000007f8 = usn 4 · slot 22 · wrap 2040
APPEND 적재 첫 읽기지연 클린아웃 없음 (5,830 ≈ 5,833). 01화의 5,842는 지연 클린아웃이 아니다

반쯤 반영 (실습/07) ​

커밋반영그대로
한 번0100,000
1,000건50,00050,000

측정 환경 ​

Oracle AI Database 26ai Free Release 23.26.2.0.0 · cpu_count 2 · db_block_size 8192 · undo_management AUTO · undo_tablespace UNDOTBS1 · undo_retention 900 · PDB 로컬 언두(LOCAL_UNDO_ENABLED TRUE) · _in_memory_undo TRUE · log_buffer 약 4MB · 온라인 리두 로그 10MB × 2.


11. Free에서 못 잰 것 ​

못 잰 것왜대신 한 것
단일 세션 self-inflicted ORA-01555 (안정 재현)IMU + 이 데이터의 CUS_ID–물리 상관 때문에 들쭉날쭉두 세션(긴 읽기 + 동시 커밋)으로 확정 재현 (§5)
수백 세션이 공유 언두를 압박하는 규모Free CPU 2개 · 작은 SGA작은 언두(6M)로 메커니즘만 재현
NOCACHE·대용량 PGA 소트가 TEMP·언두에 주는 압박작은 PGA—
ORA-01555 재현에 쓴 작은 언두운영에선 불가SYSDBA 스크립트로 분리 · 끝에서 반드시 원복 + 원복 확인

언두를 작게 바꾸는 것은 인스턴스 설정 변경이라 SYSDBA 전용이다. 이 화의 본체(커밋 주기, redo/undo, log file sync, 반쯤 반영)는 실습/01·02·07로 SYS 없이 끝난다. 01555, 30036, 지연 클린아웃만 실습/03·04·06(SYSDBA)에서 다룬다. 대규모 EE 환경은 별권에서 다룬다.


12. 원천 좌표 ​

전체 지도 → 00_자료준비/06_원서와_공식문서_지도.md PDF 페이지 = 책 페이지 − 2 · 성능고도화I_목차색인.md (공개 사이트에는 없음)

성능고도화 I권 Ch1 후반 (주 원천) ​

주제책 페이지
Redo의 역할 · Redo 로그 버퍼 · Log Writer26 · 28
Undo 세그먼트 · 트랜잭션 테이블 슬롯 · Lock Byte (← 12화가 넘긴 41·46)41 · 46
Fast Commit · Redo Strand48 · 52
블록 클린아웃 (Commit Cleanout · Delayed Cleanout)54
CR(Consistent Read) 블록과 읽기 일관성58

오라클 공식문서 ​

주제매뉴얼장 제목
Redo · Undo · Data Concurrency and Consistency (읽기 일관성 · ORA-01555)cncptData Concurrency and Consistency · Memory Architecture
COMMIT · COMMIT WRITEsqlrfCOMMIT
UNDO_RETENTION · UNDO_TABLESPACE · Undo 관리admin / refrnManaging Undo · Initialization Parameters
V$MYSTAT · V$SESSTAT · V$SESSION_EVENT · V$SYSTEM_EVENT · V$TRANSACTION · V$UNDOSTATrefrnDynamic Performance Views
블록 덤프 · 트레이스 · ADRadminManaging Diagnostic Data

이 화에서 꼭 확인할 뷰·통계 ​

sql
V$MYSTAT / V$STATNAME   -- redo size · undo change vector size · user commits · redo entries
                        -- consistent gets - examination · data blocks consistent reads - undo records applied
                        -- cleanouts only - consistent read gets · immediate (CR) block cleanout applications
                        -- CR blocks created · commit cleanouts · IMU commits
V$SESSION_EVENT         -- log file sync (내 세션) ↔ log file parallel write (LGWR 세션)
V$TRANSACTION           -- xidusn · xidslot · xidsqn (언두 세그먼트 헤더 슬롯)
V$BH                    -- status(cr · xcur) · dirty
V$UNDOSTAT              -- tuned_undoretention · maxquerylen

다음 화가 여기서 가져가는 것 ​

화가져가는 것
14"그럼 배치를 어떻게 빠르고 안전하게 돌리나": 집합 연산(INSERT…SELECT·MERGE) · APPEND · 파티션 · 병렬. P1을 다시 쓴다 (§5·§7)
1404화 인덱스와 05화 HWM의 적재 비용 청구서. redo/undo로 잰다 (§1)
15PL/SQL 루프 자체의 비용(컨텍스트 스위칭): 한 건씩 도는 구조 (§7)
16·17V$는 장애가 끝나면 사라진다. redo/undo/대기의 지나간 값을 보는 도구 (AWR·ASH)
18「SQL 코딩 가이드」·「커밋 주기 기준」: 채번과 배치는 읽기와 쓰기를 분리한다 (근거 2회: 12·13화)