데이터 입력 수정 삭제시마다Undo세그먼트에 기록, Undo데이터를 기록한공간은 해당 트랜잭션이 커밋하는순간, 다른트랜잭션이 사용할 수 있는 상태로 바뀐다.
가장 오래전에 커밋한 Undo공간부터 재사용하므로 Undo데이터가 곧바로 사라지진않겠지만,
언젠가 다른 트랜잭션 데이터로 덮어쓰이면서 사라질수밖에없다
Undo에 기록한 데이터 3가지목적
Transaction Rollback : 트랜잭션에 의한 변경사항을 최종커밋하지않고 롤백하고자할때
Transaction Recovery(Instance Recovery시 rollback단계) : Instance Crash후 Redo를이용해 roll forward단계가 완료되면 최종 커밋되지않은 변경사항까지 모두 복구됨. 따라서 셧다운된 시점에 아직 커밋되지않았던 트랜잭션들을 모두 롤백해야하는데 이때 Undo데이터 사용
Read Consistency : 읽기 일관성을 위해 사용
MVCC모델
MVCC모델을 사용하는 오라클은 두가지모드로 데이터를 읽는다
Current모드 : 디스크에서 캐시로 적재된 원본블록을 현재 상태그대로 읽는 방식
Consistent모드 : 쿼리가 시작된 이후에 다른 트랜잭션에 의해 변경된 블록을 만나면, 원본 블록으로부터 복사본(CR Copy) 블록을 만들고, 거기에 Undo데이터를 적용함으로써 쿼리가'시작된 지점'으로 되돌려서 읽는 방식
Consistent모드를 이해하라면 SCN에 대한 이해가 필요, 오라클은 시스템에서 마지막 커밋이 발생한 시점정보를 'SCN(System Commit Number)'라는 Global변수값으로 관리
이값은 기본적으로 각 트랜잭션이 커밋할때마다 1씩증가하지만, 오라클 백그랑운드 프로세서에 의해서도 조금씩 증가
또한 오라클은 각블록이 마지막으로 변경된 시점을 관리하기위해 블록 헤더에 SCN을 기록하는데 이를 '블록 SCN'
모든 쿼리는 Global변수인 SCN값을 먼저확인하고서 읽기작업시작, 이를 '쿼리 SCN'
Consistent모드는 쿼리 SCN과 블록SCN을 비교함으로써 쿼리 수행 도중에 블록이 변경됐는지를 확인하면서 데이터를 읽는 방식
데이터를 읽다가 블록SCN이 쿼리 SCN보다 더큰 블록을 만나면 복사본 블록을 만들고 Undo데이터를 적용함으로써 쿼리가 시작된 시점으로 되돌려서 읽는다.
Undo 데이터가 다른 트랜잭션에 의해 재사용됨으로써 쿼리시작 시점으로 되돌리는 작업을 실패할때
'Snapshot too old(ORA-01555)'에러가 발생
SELECT문은 항상 CONSISTENT모드로 데이터를 읽는다. 반면 수정삭제변경은 Consistent모드로 레코드를 찾고, Current모드로 데이터변경한다. Consistent모드로 DML문 시작된시점에 데이터블록찾고, 다시 Current모드로 원본 블록을 찾아서 갱신
1.7 LOCK과 DML성능
Lock을 필요이상 자주, 길게 사용하거나 레벨을 높일수락 DML성능은 느려진다
Lock을 너무 적게, 짧게 사용하거나 필요레벨 이하로 낮추면 데이터 품질이 나빠진다.
품질과 성능은 트레이드 오프관계여서 어렵다, 세심한 동시성 제어가 필요
동시성 제어(Concurrency Control) : 동시에 실행되는 트랜잭션 수를 최대화(고성능)하면서 입력/수정/삭제/검색시 데이터 무결성을 유지(고품질)하기 위해 노력하는것.
커밋과 DML성능
DML이 Lock에 의해 블로킹된 경우, 커밋은 DML성능과 직결된다
DML을 완료할 수 있게 Lock을 푸는 열쇠가 바로 커밋
모든 DBMS가 Fast Commit을 구현, 구현방식은 서로 다르지만, 갱신한 데이터가 아무리 많아도 커밋만큼은 빠르게 처리한다는 점은 같다.
커밋은 결코 가벼운작업이아니다 커밋의 내부 매커니즘
1. DB 버퍼캐시
- DB접속한 사용자를 대신해 모든 일을 처리하는 서버 프로세스는 버퍼캐시를 통해 데이터를 읽고 쓴다.
- 버퍼캐시에 변경된 블록(Dirty블록)을 모아 주기적으로 데이터 파일에 일괄기록하는 작업은 DBWR(Database Writer)프로세스가 맡는다.
2. Redo로그버퍼
- 버퍼캐시는 휘발성, DBWR프로세스가 Dirty 블록들을 데이터파일에 반영할때까지 불안한상태
- but 버퍼캐시에 가한변경을 Redo로그에도 기록해두었으므로 문제없음
버퍼캐시데이터 유실되더라도 Redo로그 이용해 언제든 복구가능
- but Redo로그도 파일, Append방식기록이라도 디스크 I/O는 느리다
- Redo로깅 성능문제 해결을 위해 로그버퍼이용 (Redo로그파일에 기록하기전 로그버퍼에 먼저 기록)
- 로그버퍼에 기록한 내용은 나중에 LGWR(Log Writer)프로세스가 Redo로그 파일에 일괄 기록 3. 트랜잭션 데이터 저장과정
1) DML문을 실행하면 Redo 로그버퍼에 변경사항을 기록한다.
2) 버퍼블록에서 데이터를 변경(레코드 추가/수정/삭제)한다. 버퍼캐시에서 찾지못하는 블록은 데이터파일에서 읽는 작업부터 한다.
3) 커밋한다.
4) LGWR 프로세스가 Redo로그버퍼 내용을 로그파일에 일괄 저장한다.
5) DBWR 프로세스가 변경된 버퍼블록들은 데이터파일에 일괄 저장한다.
- Write Ahead Logging
- 오라클은 데이터 변경전 항상 로그부터 기록
- DBWR프로세스가 Dirty블록을 디스크 기록하기전에 LGWR프로세스가 Redo로그파일에 로그를 먼저기록
- 메모리 버퍼캐시가 휘발성이어서 Redo로그를 남기는데, Redo로그마저 휘발성 로그버퍼에기록한다면 트랜잭션 데이터를 지킬수있느냐? (커밋한 트랜잭션의 영속성 보장문제)
- DBWR과 LGWR프로세스는 주기적으로 Dirty 블록과 Redo로그버퍼를 파일에 기록, LGWR은 커밋 발생시에도 파일에 기록.
- 적어도 커밋시점에는 Redo로그버퍼 내용을 로그파일에 기록한다 > Log Force at Commit
커밋 = 저장버튼
- 문서 작성시 워드프로세서는 사용자입력내용을 메모리에 기록, 저장부턴누르면 디스크파일에 저장
- 데이터베이스 트랜잭션을 문서 작업에 비유하면, 커밋은 문서작업도중에 '저장' 버튼을 누르는것
- 서버프로세스가 그때까지했던 작업을 디스크에 기록하라는 명령어
- 트랜잭션을 필요이상 길게정의하는것도, 너무자주 커밋하는것도 문제, 오래 커밋하지 않은 데이터를 계속 갱신하면 Undo공간 부족으로 시스템장애가 발생할 수 도 있다