1. 상황은 이렇습니다.
예를 들어 100명 까지 받는 예약에서 101명이 들어온 케이습니다.
2. 간단히 로직은 이렇습니다.
(※ 참고로 예약이 가능한 여부가 인원체크를 포함 10개 항목 정도 있습니다.(시간 등)
가. 예약 메인 패키지 호출
PG_APPLY.MAIN();
나. 메인 패키지 내 유효성 검사1~10 번 검사
PG_APPLY.MAIN()
IS
BEGIN
IF CHECK_1() = 'N' THEN --검사 프로시저 및 함수 호출
RETURN '1번 이유 때문에 불가능....'
END IF;
IF CHECK_2() = 'N' THEN --검사 프로시저 및 함수 호출
RETURN '2번 이유 때문에 불가능....'
END IF;
IF LIMIT_CHECK() = '인원오버' THEN --검사 프로시저 및 함수 호출
RETURN ''인원오버....'
END IF;
.
.
.
IF CHECK_10() = 'N' THEN --검사 프로시저 및 함수 호출
RETURN '10번 이유 때문에 불가능....'
END IF;
--모두 유효성을 통과 했다면 INSERT
INSERT INTO TB_APPLY............................
LOG();--로그 함수 호출
COMMIT;
END PG_APPLY.MAIN;
다. 인원 체크 함수
PG.APPLY.LIMIT_CHECK()
IS
BEGIN
현원 := SELECT COUNT(1) FROM TB_APPLY
최대인원 := SELECT COL_1 FROM ....
IF 현원 >= 최대 THEN
RETURN '인원오버'
ELSE
RETURN '신청가능'
END IF;
END LIMIT_CHECK;
3. 총 예약 건수는 몇 백개 항목에 몇 십명씩 선택하여 대략 2만건 내외 입니다.(오픈 후 10분안에 만건 정도 처리. 수강신청이란 비슷하죠)
문제는 이중에 간혹 1~10/1000초 차이로 인원이 간혹 오버 됩니다.
4. 궁금한것은..
-인원이 오버 되는 이유가 'PG.APPLY.LIMIT_CHECK()--인원체크'후에 바로 INSERT 하지 않고 다른 체크 'CHECK_##()'함수를 실행 하는 동안 인원이 오버 되는 것인지..
-그렇다면 한 트랜잭션으로 묶던지 FOR UPDATE...를 활용해서 동시성제어를 해야 하는건지 헷갈리네요.
-그런데 오라클은 DML단위 트랜잭션이 된다니... 인원체크 후에 INSERT까지 어떻하면 한 트랜잭션으로 묶어야 할지 모르겠습니다.
-동시성제어도 생각해 봤는데... 위와 같은 구조에서는 적용이 맞는건지 모르겟습니다.
고견을 부탁드립니다.
"최대인원"이 저장되어 있는 테이블에 "신청인원" 컬럼 추가
"신청인원" 은 "최대인원" 을 넘지 않도록 체크 제약 설정
신청 테이블 자료 입력시 "신청인원" 갱신되도록 트리거 설정
-- 1. 컬럼 추가 -- ALTER TABLE tb_apply_limit ADD app_cnt NUMBER; -- 2. 제약 설정 -- ALTER TABLE tb_apply_limit ADD CONSTRAINT check_limit CHECK app_cnt <= limit_cnt; -- 3. 과거 자료 정비 -- UPDATE tb_apply_limit a SET app_cnt = (SELECT COUNT(*) FROM tb_apply WHERE id = a.id) ; -- 4. 트리거 설정 -- CREATE OR REPLACE TRIGGER tri_tb_apply AFTER INSERT ON tb_apply FOR EACH ROW BEGIN UPDATE tb_apply_limit SET app_cnt = app_cnt + 1 WHERE id = :NEW.id ; END; /