h1.04 동시성 구현 사례
h3.(1) 일련번호 채번 동시성 높이기

  • Locking을 최소화하면서 채번 테이블로부터 일련번호를 채번하고자 할 때사용할 수 있는 사례
    ① 데이터가 삽입되는 시점에 실시간으로 현재의 MAX 값을 취해 1만큼 증가시킨 값을 이용
    ▶ 두 개의 트랜잭션이 동시에 같은 값을 읽었을 경우, insert 하려는 순간 PK 제약에 위배됨
    예외 (Exception) 처리를 통해 동시성을 제어
    ② MAX 값을 관리하는 별도의 채번 태이블에서 값을 가져오는 방식
    ▶ 커밋 시점의 문제 - 밑에 예제는 좀 이상함

-- 채번 테이블
create table seq tab (
  gubun varchar2(1)
, seq number
, constraint pk_seq_tab primary key(gubun, seq)
)
organization index;

-- 채번 펑션
1 create or replace function seq_nextval(l_gubun number ) return number
2 as
3   /** pragma autonomous_transaction ** /     -- 자율 트랜잭션  (프로그램 내에 commit or rollback 필요 )
4   l_new_seq seq_tab.seq%type ;  
5 begin
6   update seq tab
7   set seq = seq + 1
8   where gubun = l_gubun;
9
10   select seq into l_new_seq
11   from seq tab
12   where gubun = l_gubun;
13
14 cammit;
15 return l_new_seq;
16 end;

-- 채번 펑션 사용 
1 begin
2    update table set col1 = :x  where co12 = :y ;
3   
4   Insert into tab2 values
5   ( seq_nextval(123) , :x, :y, :z ) ;  -- seq_nextval이 롤백되면 문제가생김
6
7  1oop
8   -- do anything ...
9   end loop;
10
11  commit; 
12
13   exception
14     when others then
15      roll back;
16   end;
17 /

h3.(2) 선분이력 정합성 유지

  • 동일한 레코드를 다음과 같은 트랜잭션이 끝내기 전에 접근하면 동일성이 깨진다.

declare 
  cur_dt varchar2(14);
begin
①  cur_dt := to_char(sysdate,'yyyyrrmddhh24miss') ;
②  update  부가서비스이력
     set 종료일시 to_date( : cur_dt , 'yyyymmdd1h24miss' ) - 1/24/60/60
   where 고객 ID = 1
     and 부가서비스ID = 'A'
     and 종료일시 to date ( '99991231235959' , 'yyyyrrmddhh24miss' ) ;
   
③  insert into 부가서비스이력 (고객 ID, 부가서비스ID ,시작일시, 종료일시)
   values ( 1, 'A' , to_date( :cur_dt, 'yyyyrrmddhh24miss')
   , to date ('99991231235959' , 'yyyyrrmddhh24miss' ) )

④  commit;
end;

  • for update nowait 구문을 이용하자.

select 고객ID from 부가서비스이력
where  고객ID = 1 
  and  부가서비스ID = 'A'   
  and  종료일시 = to date ('99991231235959' , 'yyyyrrmddhh24miss' ) 
  FOR UPDATE NOWAIT