h1.7. Consistent vs Current 읽기
h3.(1) Consistent 모드 읽기와 Current 모드 읽기의 차이점
h5.Consistent 모드 읽기
- 먼저 Consistent 모드 읽기(gets in consistent mode)는 SCN 확인 과정을 거치며 쿼리가 시작된 시점을 기준으로 일관성 있는 상태로 블록을 액세스하는 것을 말한다. (항상 쿼리가 시작된 시점의 데이터를가져온다.)
- SQL 트레이스 Call 통계에서 볼 수 있는 'query' 항목과 AutoTrace에서의 'consistent gets' 항목이 지금 설명한 onsistent 모드에서 읽은 블록 수를 의미한다.
- CR copy를 생성할 필요가 없어 Current 블럭을 읽더라도 Consistent 모드에서 읽었다면 'query' 항목에 집계된다.
- select문에서 읽은 블록은 대부분 여기에 해당하며, 여기에는 CR 블록을생성하려고 Undo 세그먼트로부터 읽어들이는블록수까지 더해진다.
h5.Current 모드 읽기
- SQL문이 시작된 시점이 아니라 데이터를 찾아간 바로 그 시점의 최종 값을 읽으려고 블록을 액세스하는 것을 말한다.
- DML문을 수행할 때 주로 나타난다 .
- select for update문을 수행할 때도 Current 모드 읽기를 발견할 수 있다 .
- 블록SCN이 쿼리SCN보다 높고 낮음을 따지지 않으며 그 시점에 이미 커빗된 값이라면 그대로 받아들이고읽는다.
h5.발생하는 상황
- DML문을 수행할 때 주로 나타난다 .
- select for update문을 수행할 때도 Current 모드 읽기를 발견할 수 있다 .
- 9i 이상부터는 Full Table Scan을 하더라도 Current 모드 읽기가 발생하지 않는다.
- Index rowid를 이용한 테이블액세스 시에는 테이블 익스텐트 정보가 불펼요하므로 버전에 상관없이 Current 모
드 읽기가 발생하지 않는다. - 디스크 소트가 필요할 정도로 대량의 데이터를 정렬할 때도 Current 모드 읽기가 나타난다.
h3.(2) Consistent 모드로 갱신할 때 생기는 현상
EMP 테이블 7788번 사원의 S따」 값이 현재 1,000인 상황에서 아래 TX1,TX2 두 개
의 트랜잭션이 동시에 수행되었다. 양쪽 트랜잭션이 모두 완료된 시점에 7788번 사원의 SAL 값은얼마이어야할까?
Consistent 모드 읽기 - 쿼리 시작 시점을 기준으로 값을 읽는다
Dirty Read를 허용하지 않는 한 t1과 t2 시점에 SAL 값은 1,000이 었으므로 둘 다 1,000을 읽고 각각 100과 200을 더해 갱신을 완료한다.
최종 값은 1,000 이될 것이며, 트랜잭션 TX1의 처리 결과는 사라졌으므로 소위 말하는 Lost Update가 발생한다.
h3.(3) Current 모드로 갱신할 때 생기는 현상
- Current 모드로 처리한다면,최종값은 3,000 이 된다.
- 항상 Current 모드로만 작동하는 Sybase, SQL Server 같은 DBMS에서 수행해 보면 같은값(3,000)
- TX1 1~100,000까지의 Unique한 변호(no)를 가진 테이블에서 no> 50000 조건에 해당하는 50,000개 레코드에 대해 인덱스를 경유해 순차적으로 갱신 작업을 진행중
- 실제 SQL Server에서 테스트 해 보면, 50,001건이 갱신된다. 즉, update가 진행되는동안 새로 추가된 레코드까지도 값이변경된 것 이다.
- 만약, 인덱스를 이용해 no 값을 순차적으로 읽지 않고 Full Table Scan 방식으로 update를 진행한다면 Insert 되는 100,001번째 레코드가 삽입되는 위치에 따라 update 결과 건수가 그때그때 달라진다.
- update가 이미 진행된 블록에 insert된 레코드는 갱신 대상에서 제외되고,아직 update 되지 않은 블록에 Insert된 레코드는 갱신 대상에 포함된다.
h3.(4) Consistent 모드로 읽고, Current 모드로 갱신할 때 생기는 현상
- Current 모드로 갱신의 문제를 피하려고 오라클은 Consistent 모드로 읽고, Current 모드로 갱신한다.
<설명>
오라클에서 update문을 수행하면, 대상 레코드를 읽을 때는 Consistent 모드로 읽고 실제
값을 변경할 때는 Current 모드로 읽는다. 따라서 대상 레코드를 읽기 위한 블록 액세스는
SQL 트레이스에서 query 항목으로 계산되고,값을 변경하기 위한 블록 액세스는 current 항
목에계산된다.
- TX2는 TX1이 커밋되기를 기다렸다가 TX1이 끝나면 계속 진행한다. 하지만 이 때 7788번 사원의 SAL 값은 이미 1,100으로 바뀐 상태이므로 TX2의 update는 실패하게된다.
h3.(5) Consistent 모드로 갱신 대상을 식별하고, Current 모드로 갱신
- 오라클은 어떻게 두 개의 읽기 모드가 공존하면서 update를 처리하는 것일까?
<설명2>
1. select는 Consistent 모드로 읽는다.
2. insert, update, delete, merge는 Current 모드로 읽고 쓴다. 다만, 갱신할 대상 레코드를 식별하는 작업만큼은 Consistent 모드로 이루어진다.
Write Consistency
앞선 사례(상황 4) 에서, Consistent 모드와 Current 모드에서 읽은 값이 서로 달라 TX2의 update는 실패했다. TX2가
update를 시작한 t2 시점 기준으로는 empno = 7788 사원 레코드가 분명히 갱신 대상이었는데, 값이 달라졌다고
아무런 처리 없이 지나가도상관없는 걸까? 그렇지 않다. 데이터 정합성에 문제가 생기는 경우가 있고, 이를 방지하려고
오라클은 'Restart 메커니즘' 을 사용한다. 그때까지의 갱신을 롤백하고 update를 처음부터 다시 실행하는 것이며,
Thomas Kyte는 그의 저서에서 이것을 'Write Consistency' 라고 명명하고 있다.
h3.(6) 오라클에서 일관성 없게 값을 갱신하는 사례
- 일관성 없는 상태로 값이 갱신되는 오류{주로 생자 정의 힘수/프로시저, 트리거등을 사용할 때 발샘)
1. 첫번째 쿼리
- 스칼라 서브쿼리는 특별한 이유가 없는 한 항상 Consistent 모드로 읽기를 수행한다.
- 첫 번째 문장에서 계좌2. 잔고는 Current 모드로 읽는 반면 계좌1.잔고는 Consistent 모드로 읽는다
- 계좌1에서 변경이 발생했더라도 시작점 값을 가져온다.
2. 두번째 쿼리
- 두 번째 문장은, Current 모드로 읽어야 할 계좌2의 잔고 값을 스칼라 서브쿼리 내에서 참조하기 때문에 스칼라 서브쿼리까지도 Current 모드로 작동한다.
- update 문장이 진행되는 도중에 계좌1에서 변경이 발생했다면 그 새로운 값을 읽고,delete 발생했다면 조인에 실패해 NULL 값으로 update 될것이다.
update문이 수행되는 동안 두 테이블로부터 잔고를 변경하는 트랜잭션이 동시에 진행할수 있는상황이라면 업무특성에 맞게 SQL을작성해야만한다