1. WareValley
http://www.WareValley.com
Database Audit and Protection [ DB 접근통제 ]
Database Encryption [ DB 암호화 ]
Database Vulnerability Assessment [ DB 취약점 분석 ]
Database SQL Query Approval [ DB 작업결재 ]
Database Performance Monitoring and Management [ DB 성능관리 및 개발 ]
WareValley
Oracle Transaction
Ways of Concurrency Control
오렌지팀 윤석준 선임연구원
2. Database security and management, WareValley.
http://www.WareValley.com
Concurrency Control
비관적 동시성 제어
(Pessimistic Concurrency Control)
• 같은 Data를 동시에 수정할 것이라고 가
정
• Data를 읽는 시점에 Lock을 걸고 처리가
완료될 때까지 유지
• 동시성이 많이 떨어짐
(많이 떨어짐 ? 거의 없다고 봐야…)
낙관적 동시성 제어
(Optimistic Concurrency Control)
• 같은 Data를 동시에 수정하지 않을 것이
라고 가정
• Data를 읽을 때는 Lock을 걸지 않고,
대신 Update 시점에 앞서 읽은 Data가
변경되었는지 확인해야 함
• Lock이 유지되는 시점이 매우 짧아
동시성 확보에 유리
-> 하지만…. 귀찮 귀찮
-> 그래서 실상은 동시성 제어 없는
낙관적 프로그래밍이 대부분
3. Database security and management, WareValley.
http://www.WareValley.com
e.g. Concurrency Control
Senario SQL
SELECT itemCode, itemPrice
INTO :Code , :Price
WHERE items;
INSERT INTO orders
SELECT :Code, :custId, :orderDate, :shopId,
FROM items
WHERE itemCode = :Code
AND itemPrice = :Price;
IF sql%rowcount = 0 then
ALERT('상품 가격이 변경되었습니다.');
END if;
• 온라인 쇼핑몰에서 1,000원짜리 바나나를
주문
• 주문이 진행되는 동안 바나나 가격이
1,200원으로 수정됨
• 최종 결제 버튼을 클릭하는 순간
변경 여부를 체크하여,
변경되었으면 사용자에게 통보
4. Database security and management, WareValley.
http://www.WareValley.com
Pessimistic Concurrency Control
Senario SQL
적립 포인트 추가
( 끝 ! 다른 설명이 필요 ? )
SELECT point, visitCnt,
lastVisitedDate, amtBuy
FROM cust
WHERE id = :cust_num FOR UPDATE;
-- 적립 Point 계산
UPDATE cust
SET point = :newPoint
WHERE id = :cust_num;
잘못된 변경은 막을 수 있지만,
다른 Transaction 에서 Lock 을 걸어두고 하루 종일 있으면…
사용자 입장에서 하루 종일 기다릴 수도…
시스템 다운됬다고 생각할 수도…
5. Database security and management, WareValley.
http://www.WareValley.com
FOR UPDATE options
FOR UPDATE NOWAIT
- 대기없이 Exception ( ORA-00054 )
FOR UPDATE WAIT 3
- 3초 대기 후 Exception ( ORA-30006 )
6. Database security and management, WareValley.
http://www.WareValley.com
Optimistic Concurrency Control #1
Senario SQL
적립 포인트 추가
( OK ? )
SELECT point, visitCnt, last_dt, amtBuy
INTO :a, :b, :c, :d
FROM cust
WHERE id = :cust_num;
-- 적립 Point 계산
UPDATE cust
SET point = :newPoint
WHERE id = :cust_num
AND point = :a
AND visitCnt = :b
AND last_dt = :c
AND amtBuy = :d;
IF sql%rowcount = 0 then
ALERT('다른 사용자에 의해 변경되었습니다.');
END if;
변수이름 붙이는 것도 귀찮…
(만약 column이 4개가 아니라 20개라면…)
=> 그냥 최종변경일 하나 Check 하고 끝내자.
OK ?
7. Database security and management, WareValley.
http://www.WareValley.com
Optimistic Concurrency Control #2
SQL
SELECT point, visitCnt, last_dt, amtBuy, mod_dt
INTO :a, :b, :c, :d, :mod_dt
FROM cust
WHERE id = :cust_num;
-- 적립 Point 계산
UPDATE cust
SET point = :newPoint
WHERE id = :cust_num
AND mod_dt = :mod_dt;
IF sql%rowcount = 0 then
ALERT('다른 사용자에 의해 변경되었습니다.');
END if;
이제 Column 하나만 비교 하면 끝
하지만, 프로그램 상에서가 아니라
직접 SQL로 UPDATE 하면서
mod_dt 를 변경하지 않으면…
8. Database security and management, WareValley.
http://www.WareValley.com
Optimistic Concurrency Control #3
SQL
SELECT point, visitCnt, last_dt, amtBuy, mod_dt
INTO :a, :b, :c, :d, :mod_dt
FROM cust
WHERE id = :cust_num;
-- 적립 Point 계산
SELECT id
FROM cust
WHERE id = :cust_num;
AND mod_dt = :mod_dt FOR UPDATE;
UPDATE cust
SET point = :newPoint
WHERE id = :cust_num
UPDATE 바로 전에
FOR UPDATE 로 SELECT 한방
9. Database security and management, WareValley.
http://www.WareValley.com
Optimistic Concurrency Control #4
SQL
SELECT point, visitCnt, last_dt, amtBuy, ora_rowscn
INTO :a, :b, :c, :d, :scn
FROM cust_R
WHERE id = :cust_num;
-- 적립 Point 계산
UPDATE cust
SET point = :newPoint
WHERE id = :cust_num
AND rowscn = :scn;
IF sql%rowcount = 0 then
ALERT('다른 사용자에 의해 변경되었습니다.');
END if;
Row 단위로 SCN 등록하도록 변경
(기본값은 NoRowDepencencies 로
Block의 SCN 값이 ora_rowscn이 됨)
프로그램이 아닌 직접 SQL문으로
Data 수정했을 경우에도 적용됨
하지만 11gR2 (11.2.0.1) 에도
Bug 7338384 가 있어서
사용할 수 없다.
=> 2 개의 Transaction에서 동시에
UPDATE했을 경우 Lost Update 발생
CREATE TABLE cust_R
RowDependencies
AS
SELECT * FROM cust;
10. Database security and management, WareValley.
http://www.WareValley.com
ORA_ROWSCN
RowDependenciesNoRowDependencies
SELECT EMPNO, SAL, ORA_ROWSCN FROM SCOTT.EMP_R;SELECT EMPNO, SAL, ORA_ROWSCN FROM SCOTT.EMP;
UPDATE SCOTT.EMP
SET SAL = SAL + 20
WHERE EMPNO = 7369;
UPDATE SCOTT.EMP_R
SET SAL = SAL + 20
WHERE EMPNO = 7369;
SELECT EMPNO, SAL, ORA_ROWSCN FROM SCOTT.EMP_R;SELECT EMPNO, SAL, ORA_ROWSCN FROM SCOTT.EMP;