(1). 문장수준읽기 일관성
- 단일 SQL문이 수행되는 도중에 다른 트랜잭션에 의해 데이터의 추가,변경,삭제가 발생하더라도 일관성 있는 결과집합을 리턴하는 것.
Ex) Sybase, SQL Server 인 경우
계좌번호 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|
잔고 | 1,000 | 1,000 | 1,000 | 1,000 | 1,000 | 1,000 | 1,000 | 1,000 | 1,000 | 1,000 |
TX1> select sum(잔고) from 계좌
TX2> update 계좌 set 잔고 = 잔고 + 100 계좌번호 = 7; 1번
TX2> update 계좌 set 잔고 = 잔고 - 100 계좌번호 = 3; 2번
1. TX1 : 2번 계좌까지 읽는다.
2. TX2 : 1번을 UPDATE 을 실행한다.
3. TX1 : 6번 계좌까지 읽는다
4. TX2 : 2번을 UPDATE 하고 Commit 한다
5. TX1 : 10번 계좌까지 읽어내려간다.
결론은 값이 10,100이 나온다.
하지만 오라클은 높은 수준의 동시성을 유지하면서도 완벽한 문장수준 읽기 일관성을 보장하기 때문 값이 10,000이 나온다.
(2). Consistent 모드 블록 읽기
!current block1.jpg!
- 쿼리가 시작된 시점을 기준으로 데이터를 읽어 들인다.
- 쿼리가 시작되기 전에 이미 커밋된 데이터만 읽고 쿼리 시작 이후에 커밋된 변경사항은 읽어들이지 않는다.
- 변경이 발생한 블록을 읽을 때 는 현재의 Current 블록으로부터 CR 블록을생성 해서 쿼리가시작된 시점으로 되돌린 후 그것을 읽는다.
- Current 블록은 디스크로부터 읽혀진 후 시용자의 갱신사항이 반영된 최종 상태의 원본 블록을 말하며, CR 블록은 Current 블록에 대한 복사본이다.
- Current 블록을 여러 개의 CR Copy 블록으로 복사해 읽기 일관성을 지원하는 오라클만의 독특한 메커니즘을 다중 버전 읽기 일관성 모델(Consistency Model) 이라고 한다.
- 오라클은 SCN(System Commit Number)이라고 하는 시간정보를 이용해 테이터베이스의 일관성 있는 상태를 식별.
SCN은 읽기 일관성과 동시성 제어를 위해 사용되고, 생성된 Redo 로그 정보의 순서를 식별하는 데에도 사용되며, 데이터 복구를 위해서도 사용. - 블록 SCN : 블록이 마지막으로 변경된 시점 정보를 식별하기 위해 모든 블록 헤더에 SCN정보를 관리.(커밋 SCN과는 별도로 관리)
(3). Consistent 모드 블록 읽기의 세부원리
- 오라클에서 수행되는 모든 쿼리는 Global 변수인 SCN(System Commit Number)값을 먼저 확인하고 읽기 작업 시작(쿼리 SCN, 스냅샷 SCN)
- 읽는 블록마다 블록 SCN과 비교해 읽을 수 있는 버전인지를 판단.
1). 'Current 블록 SCN <= 쿼리SCN' 이고, commited 상태
- 쿼리가 시작된 이후에 해당 블록에 변경이 가해지지 않았다는 것을 의미. CR블록을 생성하지 않고 Current 블록을 그대로 읽는다.
- Consistent 모드에서 데이터를 읽을 때는 블록 SCN(System Change Number)이 쿼리 SCN(System Commit Number)보다 작거나 같은 블록만 읽을 수 있다.
- 이때의 블록은 Current 블록을 의미하며, Current 블록은 오직 한 개뿐이다. 데이터 갱신은 항상 Current 블록에서만 발생.
2). 'Current 블록 SCN > 쿼리SCN' 이고, commited 상태
!currnet block.jpg!
- 쿼리가 시작된 이후 해당 블록에 변경이 가해지고 커밋되었다는 것을 의미.
1) 블록 원본에 해당하는 Current 블록의 SCN이 쿼리 SCN보다 크다.
2) 블록 복사본에 해당하는 CR블록을 먼저 생성(CR Cloning)
3) 자신이 읽을 수 있는 과거 버전(쿼리 SCN보다 낮은 마지막 commited 시점)으로 되돌린다.(ITL 슬록에서 UBA(Undo Block Address)가 가리키는 Undo 블록 이용) - Undo 레코드를 읽어 CR 블록을 한 단계 이전 상태로 되돌렸는데, 거기에 커밋되지 않은 변경사항이 포함돼 있거나 블록 SCN이 높다면 다시 ITL 슬롯에 있는
UBA가 가리키는 Undo 레코드를 찾아 블록을 이전 상태로 되돌리는 작업을 계속한다. - 최종적으로 완성된 버전의 CR블록은, 블록 SCN이 쿼리 SCN보다 작으면서 커밋되지 않은 내용은 전혀 포함하지 않은 상태가 된다.
- UBA를 통해 계속적인 롤백이 가능한 것은 ITL에 대한 변경내역까지도 Undo 레코드에 기록되기 때문.
- 같은 레코드를 계속 변경할 때, 그 레코드를 조회하는 다른 세션에서의 CR블록 읽기 횟수도 계속 증가하는 것을 통해 확인 가능.
- 10g부터는 IMU(In-Memory Undo) 메커니즘 작동하므로 CR 롤백을 위해 Undo를 참조하지 않고 Shared Pool 내의 IMU Pool에 저장된 값을 이용(IMU CR rollback)
- CR 블록을 과거 상태로 되돌리는 과정에서 필요한 Undo 정보가 덮어 쓰여져 계속 롤백을 진행할 수 없을 때 'Snapshot too old(ora-1555)' 발생
- Delayed 블록 클린아웃' 과정에서 트랜잭션 테이블 슬롯이 이미 다른 트랜잭션에 의해 재사용되는 바람에 현재 읽고자 하는 클린아웃되지 않은 블록의 정확한
커밋 시점 정보를 확인할 수 없을 때도 Snapshot too old' 발생.
IMU(In-Memory Undo)
- 10g에 추가된 기능으로 Hidden 파라미터 '_in_memory_undo'와 '_imu_pools'에 의해 제어
- 이 파라미터가 TRUE면 오라클은 Undo 데이터를 Undo에 세그먼트가 아닌 Shared Pool 내의 미리 할당된 IMU Pool(KTI-Undo)에 생성
- 각 Pool은 하나의 트랜잭션에 전용으로 할당되며 im memory undo latch에 의해 보호
- IMU Pool이 다 차면 그때까지 저장해 둔 Undo 데이터를 Undo 세그먼트로 일괄 기록하며(IMU Flush), 이후 계속 발생하는 Undo 데이터는 예전처럼 Undo 세그먼트에 저장
- IMU는 작은 트랜잭션을 위해 고안된 기능이며, Undo 세그먼트 헤더 블록과 Undo 세그먼트 블록 버퍼에 대한 래치 경합 및 Pinning을 줄일 수 있다.
3).'Current 블록이 Active상태, 즉 갱신이 진행 중인 것으로 표시'돼 있을때
- 읽으려는 레코드에 Lock Byte가 설정돼 있는데, ITL에 아직 커밋 정보가 기록되지 않았다면 현재 갱신이 진행중(Active)인 것으로 인식할 수 있다.
- 오라클은 커밋 시 항상 곧바로 블록을 클린아웃(트랜잭션에 의해 설정된 로우 Lock을 해제하고 블록 헤더에 커밋 정보를 기록)하지는 않는다.
따라서 Active 상태의 블록일 때는 일단 트랜잭션 테이블로부터 커밋정보를 가져와 블록 클린아웃을 시도한다. - 쿼리 SCN 이전에 이미 커밋된 블록 : 1) 경우처럼 그 블록을 그대로 읽는다.
- 쿼리 SCN 이후에 커밋된 블록으로 확인되거나, 커밋되지 않아 아직 클린아웃할 수 없는 경우 :
2) 경우처럼 CR Copy를 만들어 쿼리 SCN보다 낮은 마지막 Committed 상태로 되돌린 후 읽는다.
Ex1) 쿼리SCN : 105일 때
- Current 블록 SCN이 105보다 작고 committed 상태이므로 그대로 읽어들이면 된다.
- Current 블록은 오직 한 개뿐이고 데이터 갱신은 항상 Current 블록에만 발생하므로 Current 블록의 SCN이
쿼리 SCN보다 작고 committed 상태라면 쿼리가 시작된 이후에 해당 블록에 변경이 가 해지지 않았다는 것을 의미.
Ex2) Ex1)에서의 Current 블록이 4 번의 갱신 과정을 거쳐 Current 블록의 SCN이 135로 증가한 상황
(쿼리SCN : 125)
- Current 블록이 active 상태일 뿐 아니라 블록 SCN이 135이므로 이 블록을 cloning해서 CR Copy를 만든다.
- 이를 한번 롤백하면 130 시점의 블록이 되고 여전히 쿼리 SCN 125보다 높기 때문 에 한번 더 롤백한다.
- 이제 CR 블록이 쿼리 SCN보다낮은 120 시점에 커밋된상태로확인되었으므로 롤백을 멈추고 그것을 읽는다.
Ex3) Ex2)와 똑같은 상황이지만 이번에는 Current 블록 SCN보다 큰 쿼리SCN을 가진 쿼리가 수행되는 경우
(쿼리SCN : 145) 마지막 Transction 상태가 Committed가 아닌 Active 상태 일 경우
- Current 블록의 SCN이 쿼리SCN보다 작지만 Tracsction 상태가 Active이기 때문에 이 블록을 cloning 해서 자신보다 낮은 마지막
committed 상태인 130 상태로 롤백하고 나서 읽게 된다.
Ex4) Ex3)에서 Transction 상태가 Active --> Committed 변경 되었을 경우
(쿼리SCN : 150)
Ex5) 쿼리SCN : 135일 때
- Current 블록이 committed 상태이지만 SCN이 140이므로 이 블록을 cloning해서 130 시점으로 롤백한 CR 블록을 읽는다.
DBA당 CR 개수 제한
- 하나의 데이터 블록마다 6개까지만 CR Copy를 허용. '_db_block_max_cr_dba' 파라미터로 제어.
- CR Copy는 LRU 리스트 상에서 항상 LRU end쪽에 위치하기 때문에 Free 버퍼가 필요할 때 1순위로 밀려난다.