3. 비관적 vs. 낙관적 동시성 제어
2010.06.06 17:26
- 비관적 동시성 제어 (Pessimistic Concurrency
Control)
- 사용자들이 같은 데이터를 동시에 수정할것이라고 가정
- 사용자가 데에터를 읽는 시점에 LOCK을 걸어 그 트랜젝션이 완료될때 까지 유지
- 낙관적 동시성 제어 (Optimistic Concurrency Control)
- 사용자들이 같은 데이터를 동시에 수정하지 않을 것이라고 가정
- 데이터를 읽을때 Lock을 설정 하지 않음
- 낙관적 동시성 제어를 사용하면 lock을 유지하는 시간이 매우 짧아져져 동시성이 높아짐
(1) 비관적 동시성 제어
SQL> create table cuspoint as select '5' as no,'1000' as
point from dual;
tx1 | tx2 | ||
SQL>
select point from cuspoint where no=5 for update; POIN ---- 1000 | t1 | ||
t2 | SQL> select * from cuspoint
where no='5'; N POIN - ---- 5 1000 | ||
t3 |
| ||
SQL> update cuspoint set point=point+1000 where no='5'; 1 row updated. | t4 | ||
SQL> commit; Commit complete. | t5 | 1 row updated. | |
t6 | SQL> SQL> select * from
cuspoint where no='5'; N POIN - ---- 5 3000 |
- for update을 사용하여 해당 고객 레코드에 Lock 을 걸어둔후 tx1세션 종료후 tx2의 세션 수행
- for update nowait --> 대기없이 Exception (Ora-00054) 를 던짐
- for update wait 3 --> 3초 대기 후 Exception (Ora-30006)을 던짐
tx1 | tx2 | |
SQL>
select point from cuspoint where no=5 for update nowait; POIN ---- 2000 | t1 | |
t2 | SQL> select point from cuspoint where no=5 for update nowait; select point from cuspoint where no=5 for update nowait * ERROR at line 1: ORA-00054: resource busy and acquire with NOWAIT specified SQL> | |
SQL>
commit; Commit complete. | t3 |
(2)
낙관적 동시성 제어
select 적립포인트, 방문횟수, 최근방문잀, 구매실적 into :a,:b, :c,:d
from 고객
where 고객번호 =:cust_num;
계산
update 고객 set 적립포인트=:적립포인트
where 고객번호 =:cust_num
and 적립포인트 = :a
and 방문횟수 = :b
and 최근방문일시 = :c
and 구매실적 = :d;
if sql%rowcount = 0 then
alert ('다른사용자에 의해 변경되었습니다.');
end if;
- 컬럼이 많을 경우 별도의 수정일시 제어 컬럼을 뒤고 where 절에 사용하여 판단할수도 있음
- 개발자가 애플리케이션 구현시 일일이 채크할수 있도록 변경해야함
- 쿼리툴등을 통해 직업수행시 lost update등의 문제가 생길수 있음
-
오라클 10g에서는 Pseudo 컬럼
ora_rowscn을 사용하여 관리 가능
ora_rowscn
- 오라클 default table 생성 / NoRowDependencies
tx1 | tx2 | |
SQL>
select e.empno,e.ename , ORA_ROWSCN,SCN_TO_TIMESTAMP(ORA_ROWSCN) from emp e; EMPNO ENAME ORA_ROWSCN SCN_TO_TIMESTAMP(ORA_ROWSCN) 7369 SMITH 2796751 06-JUN-10 03.56.52.000000000 PM 7499 ALLEN 2796751 06-JUN-10 03.56.52.000000000 PM 7521 WARD 2796751 06-JUN-10 03.56.52.000000000 PM 7566 JONES 2796751 06-JUN-10 03.56.52.000000000 PM 7654 MARTIN 2796751 06-JUN-10 03.56.52.000000000 PM 7698 BLAKE 2796751 06-JUN-10 03.56.52.000000000 PM 7782 CLARK 2796751 06-JUN-10 03.56.52.000000000 PM 7788 SCOTT 2796751 06-JUN-10 03.56.52.000000000 PM 7839 Kinng 2796751 06-JUN-10 03.56.52.000000000 PM 7844 TURNER 2796751 06-JUN-10 03.56.52.000000000 PM 7876 ADAMS 2796751 06-JUN-10 03.56.52.000000000 PM 7900 JAMES 2796751 06-JUN-10 03.56.52.000000000 PM 7902 FORD 2796751 06-JUN-10 03.56.52.000000000 PM 7934 MILLER 2796751 06-JUN-10 03.56.52.000000000 PM 14 rows selected. SQL> | t1 | SQL> select e.empno,e.ename ,
ORA_ROWSCN,SCN_TO_TIMESTAMP(ORA_ROWSCN) from emp e; EMPNO ENAME ORA_ROWSCN SCN_TO_TIMESTAMP(ORA_ROWSCN) 7369 SMITH 2796751 06-JUN-10 03.56.52.000000000 PM 7499 ALLEN 2796751 06-JUN-10 03.56.52.000000000 PM 7521 WARD 2796751 06-JUN-10 03.56.52.000000000 PM 7566 JONES 2796751 06-JUN-10 03.56.52.000000000 PM 7654 MARTIN 2796751 06-JUN-10 03.56.52.000000000 PM 7698 BLAKE 2796751 06-JUN-10 03.56.52.000000000 PM 7782 CLARK 2796751 06-JUN-10 03.56.52.000000000 PM 7788 SCOTT 2796751 06-JUN-10 03.56.52.000000000 PM 7839 Kinng 2796751 06-JUN-10 03.56.52.000000000 PM 7844 TURNER 2796751 06-JUN-10 03.56.52.000000000 PM 7876 ADAMS 2796751 06-JUN-10 03.56.52.000000000 PM 7900 JAMES 2796751 06-JUN-10 03.56.52.000000000 PM 7902 FORD 2796751 06-JUN-10 03.56.52.000000000 PM 7934 MILLER 2796751 06-JUN-10 03.56.52.000000000 PM 14 rows selected. SQL> |
t2 | SQL> update emp set ename='KING' where empno='7876'; 1 row updated. | |
SQL>
select e.empno,e.ename , ORA_ROWSCN,SCN_TO_TIMESTAMP(ORA_ROWSCN) from emp e; EMPNO ENAME ORA_ROWSCN SCN_TO_TIMESTAMP(ORA_ROWSCN) 7369 SMITH 2796831 06-JUN-10 04.00.40.000000000 PM 7499 ALLEN 2796831 06-JUN-10 04.00.40.000000000 PM 7521 WARD 2796831 06-JUN-10 04.00.40.000000000 PM 7566 JONES 2796831 06-JUN-10 04.00.40.000000000 PM 7654 MARTIN 2796831 06-JUN-10 04.00.40.000000000 PM 7698 BLAKE 2796831 06-JUN-10 04.00.40.000000000 PM 7782 CLARK 2796831 06-JUN-10 04.00.40.000000000 PM 7788 SCOTT 2796831 06-JUN-10 04.00.40.000000000 PM 7839 Kinng 2796831 06-JUN-10 04.00.40.000000000 PM 7844 TURNER 2796831 06-JUN-10 04.00.40.000000000 PM 7876 KING 2796831 06-JUN-10 04.00.40.000000000 PM 7900 JAMES 2796831 06-JUN-10 04.00.40.000000000 PM 7902 FORD 2796831 06-JUN-10 04.00.40.000000000 PM 7934 MILLER 2796831 06-JUN-10 04.00.40.000000000 PM 14 rows selected. SQL> | t3 |
- tx1에서 scn 이 2796751이었어나 tx2에서 update 완료후 2796831
- ora_rowscn 을 where 절에서 사용하여 낙관적 동시성 제어 수행 가능
- rowdependences : 테이블 생성시 row단위로 scn 을 처리
SQL> create
table t rowdependences nologging as select * from emp; SQL> update t set ename='Kinng' where empno='7839'; SQL> commit; Commit complete. SQL> select e.empno,e.ename , ORA_ROWSCN,SCN_TO_TIMESTAMP(ORA_ROWSCN) from t e; EMPNO ENAME ORA_ROWSCN SCN_TO_TIMESTAMP(ORA_ROWSCN) ---------- ---------- ---------- ------------------------------------- 7369 SMITH 2796616 06-JUN-10 03.50.47.000000000 PM 7499 ALLEN 2796616 06-JUN-10 03.50.47.000000000 PM 7521 WARD 2796616 06-JUN-10 03.50.47.000000000 PM 7566 JONES 2796616 06-JUN-10 03.50.47.000000000 PM 7654 MARTIN 2796616 06-JUN-10 03.50.47.000000000 PM 7698 BLAKE 2796616 06-JUN-10 03.50.47.000000000 PM 7782 CLARK 2796616 06-JUN-10 03.50.47.000000000 PM 7788 SCOTT 2796616 06-JUN-10 03.50.47.000000000 PM 7839 Kinng 2796737 06-JUN-10 03.56.13.000000000 PM 7844 TURNER 2796616 06-JUN-10 03.50.47.000000000 PM 7876 ADAMS 2796616 06-JUN-10 03.50.47.000000000 PM EMPNO ENAME ORA_ROWSCN SCN_TO_TIMESTAMP(ORA_ROWSCN) ---------- ---------- ---------- ------------------------------------------ 7900 JAMES 2796616 06-JUN-10 03.50.47.000000000 PM 7902 FORD 2796616 06-JUN-10 03.50.47.000000000 PM 7934 MILLER 2796616 06-JUN-10 03.50.47.000000000 PM 14 rows selected. SQL> |
- 참고) ora_rowscn 은
smon 프로세스가 관리하는 scn과 timestamp 매핑테이블에 영향을 받으며
매핑테이블 갱신주기는 5일 (= scn으로 timestamp 를 확인할수 있는 시기는 5일)
참고 :
Thread: SELECT FOR UPDATE NOWAIT | WAIT 기능 소개
http://forums.oracle.com/forums/thread.jspa?threadID=471919&tstart=208
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
47 |
2. 트랜잭션 수준 읽기 일관성
![]() | 휘휘 | 2010.06.06 | 20213 |
» | 3. 비관적 vs. 낙관적 동시성 제어 | 휘휘 | 2010.06.06 | 8329 |
45 | 4. 동시성 구현 사례 | 토시리 | 2010.06.06 | 11079 |
44 |
5. 오라클 Lock
![]() | 휘휘 | 2010.06.06 | 26512 |
43 |
7. Response Time Analysis 방법론과 OWI
![]() | balto | 2010.06.13 | 8202 |
42 | 8. Statspack / AWR | balto | 2010.06.13 | 12910 |
41 | 9. ASH(Active Session History) | 실천하자 | 2010.06.13 | 15731 |
40 | 11. End-To-End 성능관리 | 휘휘 | 2010.06.13 | 8248 |
39 |
12. 데이터베이스 성능 고도화 정석 해법
![]() | 휘휘 | 2010.06.13 | 7248 |
38 |
5. V$SYSSTAT
[1] ![]() | 토시리 | 2010.06.13 | 9977 |
37 | 10. V$SQL | 실천하자 | 2010.06.13 | 12803 |
36 | 6. V$SYSTEM_EVENT | 토시리 | 2010.06.14 | 6641 |
35 |
3. 라이브러리 캐시 구조
![]() | balto | 2010.06.27 | 9957 |
34 |
4. 커서 공유
![]() | balto | 2010.06.27 | 9324 |
33 |
1. SQL과 옵티마이저
![]() | 휘휘 | 2010.06.27 | 7326 |
32 |
2. SQL 처리과정
![]() | 휘휘 | 2010.06.27 | 20929 |
31 | 4장. 라이브러리 캐시 최적화 원리 | 휘휘 | 2010.06.27 | 7032 |
30 | 5. 바인드 변수의 중요성 | 실천하자 | 2010.06.27 | 11862 |
29 |
6. 바인드 변수의 부작용과 해법
![]() | 실천하자 | 2010.06.27 | 14868 |
28 |
7. 세션 커서 캐싱
![]() | 토시리 | 2010.06.29 | 10711 |