- 데이터가 삽입되는 시점에 실시간으로 현재의 MAX 값을 취해 1만큼 증가시킨 값을 이용하는 방식
=> PK제약 같은 예외처리를 통하여 동시성 제어(ex : 동시에 Insert 시)
- MAX 값을 관리하는 별도의 채번 테이블에서 값을 가져오는 방식 -
- 번호 할당을 위한 Table -
create table seq_tab (
gubun varchar2(1),
seq number,
constraint pk_seq_tab primary key(gubun, seq)
)organization index;
- 현재의 값에 1을 증가 시켜 사용자에게 리턴하는 Function -
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;
/
- 위의 Table과 Function을 이용하여 채번되는 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;
/
- 위의 Transaction이 어떠한 이유로 Insert 후 Rollback 되었을 경우
=> Insert 전의 Update만 commit 되어 일관성 깨짐
- seq_nextval Function에서 Commit을 안하고 종료 하였을 경우
=> Transaction이 종료 될때까지 seq_tab(채번) Table에 Lock 발생
# 해결 방안 : "autonomous_transaction" 이용 - Main Transaction과는 별도로 Sub Transaction만 Commit하는 기능 제공
create or replace function seq_nextval(l_gubun number) return number as
pragma autonomous_transaction;
l_new_seq seq_tab.seq%type;
begin
.
.
=> 선분이력의 DML(Update, Insert, Delete) 실행으로 발생할 수 있는 동시성 문제(정합성 등) 해결 사례
\- 점이력 : Data의 변경시점만을 관리 => Data + 변경시점
\- 선분이력 : Data의 변경된 시작 시점과 종료시점을 함께 관리 => Data + 시작시점 + 종료시점
- 최종 선분이력을 새로운 선분이력으로 변경하는 Transaction-
declare
cur_dt varchar2(14);
begin
cur_dt := to_char(sysdate, 'yyyymmddhh24miss') ;
update 부가서비스이력
set 종료일시 = to_date(:cur_dt, 'yyyymmddhh24miss') - 1/24/60/60
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 되는 Transaction
- 선행 Transaction이 작업 중일때 후행 Transaction이 동일 Data에 대하여 변경 작업을 하여 일관성이 깨짐
# 해결 방안 : 아래의 구문을 Transaction내의 Update 전에 추가
select 고객ID
from 부가서비스이력
where 고객ID = 1
and 종료일시 = to_date('99991231235959', 'yyyymmddhh24miss')
for update nowait ;
select 고객ID
from 고객
where 고객ID = 1
for update nowait ;
- Transaction 내에서 DML 작업 전에 select for update를 이용하여 Transaction이 순차 진행을 할 수 있도록 함
- 부가서비스이력이 없는 고객도 Lock 설정이 될 수 있도록 상위 엔티티인 고객 Table에도 select for update 설정