7._Consistent_vs._Current_모드_읽기
2012.03.18 18:17
1. Consistent 모드 읽기와 Current 모드 읽기의 차이점
Consistent Mode Read | Current Mode Read | |
정의 | SCN 확인후 Query 시작 시점을 기준으로 일관성 있는 Data Read 즉 Query 시작 시점의 Data를 읽어 오는것 | Data를 찾아간 시점의 최종값을 읽어 온다 항상 Current Block 를 읽는다. |
SqlTrace 통계항목 | Query 항목 ※ Select 문에 의한 Block 수 + CR Block 생성을 위한 Undo Segment Block | Current 항목 |
AutoTrace 통계항목 | Consistent gets | db block gets |
발생 Query | Select 문 | DML 문 사용시 주로 발생 select for update 8i에서의 full table scan disk sort가 필요한 위한 대량 sort |
※ Consistent Mode로 읽기 시작한 경우 CR Block 를 생성할 필요가 없어 Current Block를 읽더라도 통계항목은 Consistent 의 항목으로 수집 된다.
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.01 0.04 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 149 0.61 0.75 0 7372 0 2211
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 151 0.62 0.80 0 7372 0 2211
[AUTO_TRACE]
Statistics
----------------------------------------------------------
56839 recursive calls
2 db block gets
45992 consistent gets
19750 physical reads
0 redo size
2837 bytes sent via SQL*Net to client
708 bytes received via SQL*Net from client
5 SQL*Net roundtrips to/from client
101 sorts (memory)
0 sorts (disk)
60 rows processed
2. Consistent 모드로 갱신할때 생기는 현상
- <상황1> 현재 emp 테이블 empno 7788의 sal = 1000
TX1 |
| TX2 |
update emp set sal = sal + 100 where empno = 7788; | T1 |
|
| T2 | update emp set sal=sal+200 where empno=7788; |
commit; | T3 |
|
| T4 | Commit; |
- 위의 두개의 Transaction 수행 후 empno=7788의 sal 값은 1200 or 1300 ?
- Consistent Mode로 생각한다면 답은 1200 : Consistent Mode로 읽는 다면 읽기 시작한 시점의 TX1 과 TX2의 sal 값은 모두 1000이다 그러므노 마지막에 수행된 tx2에 의해 1200 이 된다.
- Consisten Mode로 읽어 Transaction을 처리한경우 TX1의 Transaction은 실종되는 현상이 발생 한다.
3. Current 모드로 갱신할때 생기는 현상
- <상황2> 현재 emp 테이블 empno 7788의 sal = 1000
TX1 |
| TX2 |
update emp set sal = 2000 where empno = 7788 and sal=1000; | T1 | |
| T2 | update emp set sal=3000 where empno=7788 and sal=2000; |
Commit; | T3 |
|
| T4 | Commit; |
- Current Mode로 읽어 처리 된경우 TX2 가 읽는 시점에는 TX1에 의해 Current Block sal=2000 이 되어 있으므로 결과는 sal=3000 이 된다.
- Sybase, SQL server 과 같이 항상 current 모드로 적용 되는 DBMS에서는 항상 3000 이 된다.
- <상황3> 테이블 t는 1~100,000 까지의 Unique한 no를 가진 테이블
TX1 |
| TX2 |
update t set no = no + 1 where no > 50000; | T1 |
|
| T2 | insert into t values(100001, 100001); |
| T3 | commit; |
commit; | T4 | |
- TX1에 의해 갱신되어야 할 대상에 TX2의 data 포함 ???
- 실제로 MSSQL에서는 index를 통해 순차적으로 읽지 않는 다면 txt2의 데이터를 포함한 50001개의 데이터가 갱신 되는현상을 볼수 있다.
- DATA의 삽입 위치에 따라 갱신 대상이 변경 된다는 의미이다.
4. Consistent 모드로 읽고, Current 모드로 갱신할 때 생기는 현상
|
- <상황4> 현재 emp 테이블 empno 7788의 sal = 1000
TX1 |
| TX2 |
update emp set sal = sal + 100 where empno = 7788 and sal=1000; | T1 |
|
| T2 | update emp set sal= sal + 200 where empno=7788 and sal=1000; |
Commit; | T3 |
|
| T4 | Commit; |
- TX2 시점의 Sal 값은 current 모드로 읽는 경우 1100 이므로 TX2 는 실패하게 된다.
- 오라클의 원리이 대상을 추출 할때 Consistent Mode로 읽는 다면 TX2의 실패를 이해하기 힘들다.
5. Consistent 모드로 갱신대상을 식별하고, Current 모드로 갱신
- 4절의 내용을 정확하게 pseudo 코드로 설명하면 다음과 같다.
for c in
{ select rowid rid from emp /* Consistent 모드 읽기 단계1) */
where empno = 7788 and sal = 1000
}
loop
update emp set sal = sal + 200 /* Current 모드 읽기 단계2) */
where empno = 7788 and sal = 1000
and rowid = c.rid
;
end loop
- 단계1) rowid를 찾는 과정에서는 consistent mode로 찾는다.
- 단계2) Consistent mode의 rowid 해당 하는 데이터에 lock를 설정한후 current 모드로 update/delete 대상을 읽어 DML 처리 한다.
|
위의 요약에 따른 <상황2>, <상황3> 에 대한 처리 절차
- <상황2> 현재 emp 테이블 empno 7788의 sal = 1000
TX1 |
| TX2 |
update emp set sal = 2000 where empno = 7788 and sal=1000; | T1 |
|
| T2 | update emp set sal=3000 where empno=7788 and sal=2000; |
commit; | T3 |
|
| T4 | Commit; |
- SQL Server => empno = 7788 최종 sal = 3000
- Oracle => TX2 처리 대상 추출 불가로 empno = 7788 최종 sal = 2000
- T2 시점에 TX1의 transaction이 commit 되지 않은 상태 이므로 대상을 추출할때의 Consistent 모드에서 제외된다.
TX1 |
| TX2 |
update t set no = no + 1 where no > 50000; | T1 |
|
| T2 | insert into t values(100001, 100001); |
| T3 | commit; |
commit; | T4 | |
- 오라클에서는 TX2의 삽입 위치와 상관없이 TX1의 갱신 건수는 항상 50000건
- TX1의 대상 추출 당시 Consistent 모드에 의해 TX2의 대상이 제외된다.
6. 오라클에서 일관성 없게 값을 갱신하는 사례
Query 1
update 계좌2
set 총잔고 = 계좌2.잔고 + (select 잔고 from 계좌1 where 계좌번호 = 계좌2.계좌번호)
where 계좌번호 = 7788;
Query 2
update 계좌2
set 총잔고 = (select 계좌2.잔고 + 잔고 from 계좌1 where 계좌번호 = 계좌2.계좌번호)
where 계좌번호 = 7788;
- 스칼라 서브 쿼리는 이유가 없는 한 항상 Consistent 모드 읽기 수행
- Query1의 계좌2.잔고는 current 모드로 읽는 반면
- Query2의 계좌2.잔고는 Consistent 모드로 읽는다.
오후 7:44:50 SQL> create table 계좌1 (계좌번호 number,계좌명 varchar2(10), 잔고 number); |
TX 1 | 오후 7:48:53 SQL> update 계좌1 set 잔고 = 잔고 + 100 where 계좌번호 = 10; |
TX 2 | 오후 7:50:34 SQL> update 계좌2 set 총잔고 = 계좌2.잔고 + (select 잔고 from 계좌1 where 계좌번호 = 계좌2.계좌번호) where 계좌번호 = 10; |
TX 1 | 오후 7:50:07 SQL> commit; |
TX 2 | 오후 7:51:36 SQL> commit; |
오후 7:52:00 SQL> select 계좌1.잔고, 계좌2.잔고,계좌2.총잔고,계좌1.잔고 + 계좌2.잔고 총잔고2 |
이러한 오류를 해결 하기 위하여 다음과 같이 주의 하여 Query를 작성해야 한다.
오후 8:01:18 SQL> select 계좌1.잔고, 계좌2.잔고,계좌2.총잔고,계좌1.잔고 + 계좌2.잔고 총잔고2 |
TX 1 | 오후 8:01:18 SQL> update 계좌1 set 잔고 = 잔고 + 100 where 계좌번호 = 20; |
TX 2 | 오후 8:01:28 SQL> update 계좌2 set 총잔고 = (select 계좌2.잔고 + 잔고 from 계좌1 where 계좌번호 = 계좌2.계좌번호) where 계좌번호 = 20; |
TX 3 | 오후 8:01:36 SQL> commit; |
TX 2 | 오후 8:01:40 SQL> commit; |
- TX2 의 계좌1.잔고와 계좌2.잔고를 모두 Current 모드로 읽었기 때문에 일관성 있게 갱신됨
오후 8:01:49 SQL> select 계좌1.잔고, 계좌2.잔고,계좌2.총잔고,계좌1.잔고 + 계좌2.잔고 총잔고2 |
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
6 | 5._Undo | dasini | 2012.03.11 | 25088 |
5 | 2._DB_버퍼_캐시 | 시와처 | 2012.03.04 | 10442 |
4 | 1._기본_아키텍처 | AskZZang | 2012.03.02 | 8363 |
3 | 1_장._오라클_아키텍처 | AskZZang | 2012.03.02 | 5001 |
2 | 3._버퍼_Lock | 박영창 | 2012.02.24 | 7293 |
1 | Front Page | 운영자 | 2012.02.21 | 131212 |