SELECT 적립포인트, 방문횟수, 최근방문일시, 구매실적 FROM 고객
WHERE 고객번호 = :CUST_NUM FOR UPDATE;
-- 새로운 적립 포인트 계산
UPDATE 고객 SET 적립포인트 = :적립포인트 WHERE 고객번호 = :CUST_NUM
FOR UPDATE NOWAIT --> 대기없이 Exception (ORA-00054)을 던짐
FOR UPDATE WAIT 3 --> 3초 대기 후 Exception (ORA-30006)을 던짐
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
ALTER( '다른 사용자에 의해 변경되었습니다.');
END IF;
SELECT 적립포인트, 방문횟수, 최근방문일시, 구매실적, 변경일시
INTO :A, :B, :C, :D, :MOD_DT
FROM 고객
WHERE 고객번호 = :CUST_NUM;
--새로운 적립포인트 계산
--다른 트랜잭션에 의해 설정된 Lock에 때문에 동시성이 저하되는 것을 예방할 수 있다.
SELECT *
FROM 고객
WHERE 고객번호 = :CUST_NUM
AND 변경일시 = :MOD_DT
FOR UPDATE NOWAIT; -- NOWAIT
UPDATE 고객 SET 적립포인트 = :적립포인트
WHERE 고객번호 = :CUST_NUM
AND 변경일시 = :MOD_DT;
IF SQL%ROWCOUNT = 0 THEN
ALTER( '다른 사용자에 의해 변경되었습니다.');
END IF;
CREATE TABLE WORK_TRAN_MASTR ROWDEPENDENCIES AS
SELECT 1000 + LEVEL AS A , 0 AS STATUS, 0 AS STATUS_A, 0 AS STATUS_B FROM DUAL CONNECT BY LEVEL <= 100
ALTER TABLE WORK_TRAN_MASTR modify ( A number NOT NULL )
CREATE UNIQUE INDEX JLIVE.WORK_TRAN_MASTR_PK ON JLIVE.WORK_TRAN_MASTR
(A)
LOGGING
TABLESPACE JLIVE01
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS UNLIMITED
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
NOPARALLEL;
ALTER TABLE JLIVE.WORK_TRAN_MASTR ADD (
CONSTRAINT WORK_TRAN_MASTR_PK
PRIMARY KEY
(A)
USING INDEX JLIVE.WORK_TRAN_MASTR_PK);
-- SESSION 1
DECLARE
AA NUMBER;
ORA NUMBER;
BEGIN
FOR IDX in 1 .. 100 LOOP
--DBMS_OUTPUT.ENABLE;
SELECT a, ora_rowscn
INTO AA, ORA
FROM WORK_TRAN_MASTR
WHERE ROWNUM = 1 and STATUS = 0;
--DBMS_OUTPUT.PUT_LINE('A : ' || TO_CHAR( AA ));
--DBMS_OUTPUT.PUT_LINE('ora_rowscn : ' || TO_CHAR( ORA ));
dbms_lock.sleep( DBMS_RANDOM.VALUE * 0.5 );
UPDATE WORK_TRAN_MASTR
SET STATUS_A = 1
, STATUS = 1
WHERE A = AA
AND ora_rowscn = ORA;
COMMIT;
END LOOP;
END;
/
-- SESSION 2
DECLARE
AA NUMBER;
ORA NUMBER;
BEGIN
FOR IDX in 1 .. 100 LOOP
--DBMS_OUTPUT.ENABLE;
SELECT a, ora_rowscn
INTO AA, ORA
FROM WORK_TRAN_MASTR
WHERE ROWNUM = 1 and STATUS = 0;
--DBMS_OUTPUT.PUT_LINE('A : ' || TO_CHAR( AA ));
--DBMS_OUTPUT.PUT_LINE('ora_rowscn : ' || TO_CHAR( ORA ));
dbms_lock.sleep( DBMS_RANDOM.VALUE * 0.5 );
UPDATE WORK_TRAN_MASTR
SET STATUS_B = 1
, STATUS = 1
WHERE A = AA
AND ora_rowscn = ORA;
COMMIT;
END LOOP;
END;
/
- 강좌 URL : http://www.gurubee.net/lecture/3079
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.