오라클 성능 고도화 원리와 해법 I (2009년)
동시성 구현 사례 0 0 3,884

by 구루비 Concurrency 트랜잭션 [2009.11.13]


h2.동시성 구현 사례
h4.채번 하는 방법

  1. Sequence 이용하는 방법
  2. 데이터가 삽입되는 시점에 실시간으로 현재의 MAX값을 취해 1만큼 증가시킨 값을 이용
    • 문제점 : 실시간으로 MAX값을 얻어 처리할 때는 두 개의 트랜잭션이 동시에 같은 값을 읽을 경우, insert 하려는 순간 PK제약에 위배. ? Exception 처리를 통해 그다지 어렵지 않게 동시성을 제정할 수 있음
  3. MAX값을 관리하는 별도의 채번 테이블에서 가져오는 방식
    • 문제점 : 채번 테이블을 사용할 때는 채번 후 다음 처리로 진행하기 전에 채번 테이블 값을 1만큼 증가시키는 갱신을 수행해야 함

-- 테이블 생성
Create table seq_tab (
Gubun varchar2(1),
Seq    number,
Constraint pk_seq_tab primary key(gubun,seq))

-- Procedure 생성
Create or replace function seq_nextval (l_gubun number) return number
As
/** pragma autonomous_transaction; **/
l_new_seq seq_tab.seq%type;

begin
 update seq_tab
   set    seq = seq + 1
   where gubun = l_gubun;

   select seq into l_new_seq
   from seq_tab
   where gubun = l_gubun;


   commit;
   return l_new_seq;
end;
/


--Transaction
Begin
 Update tab1 set col1 = :x where col2 = :y;

Insert into tab2 values
(seq_nextval(123), :x, :y, :z);

Loop
 --do anything....
End loop;

Commit;

Exception
 When others then
  Rollback;
End;



    • 문제점은 커밋 시점이다. 만약 앞서 정의한 seq_nextval 함수처럼 커밋을 한다면, 어떤 이유에서 메인 트랜잭션이 라인 4 insert 이후에 롤백될 경우 문제가 생긴다. 즉 update(Function의 update)는 이미 커밋된 상태가 되어 데이터의 일관성이 깨지게 된다.
    • 만약 seq_nextval함수에서 커밋을 안하고 함수를 빠져나오면 메인 트랜잭션이 모두 종료될 때까지 채번 테이블에 Lock이 걸린 상태가 유지 되므로 동시 채번이 빈번히 발생하는 상황에서 심각한 성능 저하를 일으키게 될 것이다.
    • 'autonomous 트랜잭션'이라고 하여 서브 트랜잭션만 따로 커밋하는 기능을 제공한다.

h4.선분이력 정합성 유지


Declare
 cur_dt varchar2(14);
begin
① cur_dt := to_char(sysdate, 'yyyymmddhh24miss');

② update 부가서비스이력
   Set     종료일시 = to_date(:cur_dt, 'yyyymmddhh24miss');
   Where  고객ID = 1
   And     부가서비스ID = 'A'
   And     종료일시 = to_date('99991231235959', 'yyyymmddhh24miss');

③ insert into 부가서비스이력(고객ID, 부가서비스ID,시작일시,종료일시)
   Values(1, 'A', to_date(:cur_dt, 'yyyymmddhh24miss'),
   To_date('99991231235959', 'yyyymmddhh24miss'));

④ commit;
End;

    • 이 트랜잭션은 기존의 선분이력을 끊고 새로운 이력 레코드를 추가하는 전형적인 처리 루틴이다.
    • 신규 등록 건이면 ②번 update문에서 실패하고 ③번에서 한 건이 insert될 것이다.
  • 만일 첫 번째 트랜잭션이 ①을 수행하고 ②로 진입하기 직전에 어떤 이유에서건 두 번째 트랜잭션이 동일 이력에 대해 ①~④를 먼저 진행해 버린다면 선분이력이 깨지게 된다. 따라서 트랜잭션이 순차적으로 진행할 수 있도록 직렬화 장치를 마련해야 한다.
    • ①번 문장을 수행하기 직전에 "select for update"문을 이용해 해당 레코드에 Lock을 설정 하면 된다.
    • 하지만 부가서비스이력에 Lock을 걸어 동시성을 관리하려 한다면 기존에 부가서비스이력이 전혀 없던 고객일 경우 Lock이 걸리지 않는다. 그러면 동시에 두개 트랜?신이 ③번 insert문으로 진입할 수 있고, 결과적으로 시작일시는 다르면서 종료일시 같은 두 개의 이력 레코드{}{}가 생긴다.
    • 따라서 부가서비스이력의 상위 엔티티인 고객 테이블에 Lock을 설면 완벽하게 동시성 제어를 할 수 있다.

문서에 대하여

  • 최초작성자 : 미녀씨
  • 최초작성일 : 2009년 10월 22일
  • 이 문서는 오라클클럽 코어 오라클 데이터베이스 스터디 모임에서 작성하였습니다.
  • {*}이 문서의 내용은 (주)비투엔컬설팅에서 출간한 '오라클 성능 고도화 원리와 해법I'를 참고하였습니다.*
"코어 오라클 데이터베이스 스터디 모임" 에서 2009년에 "오라클 성능 고도화 원리와 해법 I " 도서를 스터디하면서 정리한 내용 입니다.

- 강좌 URL : http://www.gurubee.net/lecture/3016

- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^

- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입