트렌젝션
트렌젝션 개요
- 트렌젝션은 파일 시스템과 데이터베이스를 구분짓는 특징 중 하나이다.
- 파일시스템은 쓰기 도중 운영체제가 갑자기 정지하면 훼손 가능성이 크다
- 파일 두개가 동기화 된 상태를 유지하더라도 변경 작업 중 운영체제가 정지하면 두 개의 동기화가 깨질 수 있다
- 트렌젝션은 일관된 상태에서 다음 일관된 상태로 데이터베이스를 전환한다. 일관성을 유지하는 것이 트렌젝션의 기능이다
- 트렌젝션의 4가지 특성은 원자성/일관성/고립성/지속성이다
트렌젝션 제어
오라클 특성
- 트렌젝션은 묵시적으로 데이터를 변경하는 첫 번 째 문장과 함께 시작한다
- SET TRANSACTION / DBMS_TRANSACTION 으로 명시적으로 시작 가능하다
- COMMIT/ROLLBACK 으로 종료 가능하다
- 오라클의 트렌젝션 원자성 보호는 개별 문장에도 적용된다
- 한 문장이 실패했다고 그 전에 수행 한 다른 문장이 롤백되지는 않는다
트렌젝션 제어 문장
COMMIT
- COMMIT(COMMIT WORK) 로 사용 할 수 있다.
- 주석으로 라벨을 붙여서 의심되는 분산 트렌젝션을 강제 커밋 할 수도 있으며
- 비동기 커밋을 수행할 수도 있다
ROLLBACK
- ROLLBACK(ROLLBACK WORK) 로 사용할 수 있다
- 언두에서 변경 전 정보를 읽어 다시 되돌린다
SAVEPOINT
- 트렌젝션 중간에 표시하여 부분 롤백을 가능하게 만들어 준다
ROLLBACK TO [ SAVEPOINT ]
- SAVEPOINT 지정 한 부분까지 부분 롤백이 가능하다
SET TRANSACTION
- 트렌젝션 고립 수준이나 속성을 설정할 수 있다
- SET TRANSACTION READ ONLY; / SET TRANSACTION READ WRITE;
원자성
트리거의 경우
- DML 문장에 트리거 설정 하였을 경우 DML 에 딸려있는 트리거도 문장의 일부분으로 간주한다.
- DML 문장이 실패하면 트리거가 동작할지라도 그 이전 문장까지 롤백한다
SQL> create table t2 ( cnt int );
Table created.
SQL> insert into t2 values ( 0 );
1 row created.
SQL> commit;
Commit complete.
SQL> create table t ( x int check ( x>0 ) );
Table created.
SQL> create trigger t_trigger
before insert or delete on t for each row
begin
if ( inserting ) then
update t2 set cnt = cnt + 1;
else
update t2 set cnt = cnt - 1;
end if;
dbms_output.put_line('I fired and updated '||sql%rowcount||' rows');
end;
/
Trigger created.
SQL> set serveroutput on
SQL> insert into t values (1);
I fired and updated 1 rows
1 row created.
SQL> insert into t values(-1);
I fired and updated 1 rows
insert into t values(-1)
*
ERROR at line 1:
ORA-02290: check constraint (LIM.SYS_C0021582) violated
SQL> select * from t2;
CNT
----------
1
SQL> rollback;
Rollback complete.
SQL> select * from t2;
CNT
----------
0
SQL> select * from t;
no rows selected
SQL>
프로시저의 경우
- PL/SQL 블록도 문장으로 간주한다
- 아래와 같은 예제가 동작 하는 이유는 Procedure 내부에 자체적으로 Commit/Rollback 이 없기 때문이다
SQL> create or replace procedure p as
2 begin
3 insert into t values(1);
4 insert into t values(-1);
5 end;
6 /
Procedure created.
SQL>
SQL> exec p;
I fired and updated 1 rows
I fired and updated 1 rows
begin
*
ERROR at line 1:
ORA-02290: check constraint (LIM.SYS_C0021582) violated
ORA-06512: at "LIM.P", line 4
ORA-06512: at line 2
SQL> select * from t2;
CNT
----------
0
SQL> select * from t;
no rows selected
SQL>
- PL/SQL 블록에 익셉션 처리 할 경우는 경우가 달라진다
SQL> begin
2 p;
3 exception when others then
4 dbms_output.put_line('Error : '||sqlerrm);
5 end;
6 /
I fired and updated 1 rows
I fired and updated 1 rows
Error : ORA-02290: check constraint (LIM.SYS_C0021582) violated
PL/SQL procedure successfully completed.
SQL> select * from t;
X
----------
1
SQL> select * from t2;
CNT
----------
1
SQL>
-------- 프로시저 안에 예외처리를 해도 마찬가지 ---------
SQL> create or replace procedure p as
begin
insert into t values(1);
insert into t values(-1);
exception when others then
dbms_output.put_line('Error : '||sqlerrm);
end;
/
Procedure created.
SQL> exec p;
I fired and updated 1 rows
I fired and updated 1 rows
Error : ORA-02290: check constraint (LIM.SYS_C0021582) violated
PL/SQL procedure successfully completed.
SQL> select * from t;
X
----------
1
SQL> select * from t2;
CNT
----------
1
SQL>
- 이유는 예외처리로 인해 오류가 발생하면 PLSQL Block 을 롤백하는 기능이 수행되지 않았기 때문이다
DDL과 원자성
- DDL 문장을 수행하면 그 전까지 진행 중이던 트렌젝션은 묵시적으로 COMMIT 된다
- 이 후 DDL 이 성공하면 반영하고 실패하면 DDL 은 롤백한다
- DDL 자체도 묵시적 COMMIT 으로 동작한다.
영속성
- 트렌젝션이 커밋 되면 변경 데이터는 DBMS 에 영구적으로 반영한다
- 다음과 같은 예외 사항이 있다
영속성의 예외(오라클)
- COMMIT 문의 확장인 COMMIT WRITE NOWAIT 기능을 사용 할 경우
- DB 링크를 사용하지 않고 비 분산 환경에서 PLSQL 코드 블록 내에서 커밋 하는 경우
COMMIT WRITE NOWAIT
- 10gR2 이상부터 COMMIT 에 WRITE 를 붙일 우 있다
COMMIT WRITE WAIT 이 기본 값이다
- 커밋 시 LGWR 프로세스가 리두 버퍼에서 온라인 리두로그에 기록한다
COMMIT WRITE NOWAIT 은 다음과 같이 동작한다
- LGWR 프로세스가 리두 버퍼에서 온라인 리두로그에 기록하기 전에 커밋을 완료한다
- 사용자에게 커밋 완료 상태를 보여주지만 실제로 파일에 쓰이지 않았기 때문에 영속성을 보장하기 어렵다
- 로그 파일 기록으로 인한 물리적 I/O 시간을 줄이기 위한 목적으로 사용 가능하나 신중하게 사용하여야 한다.
- COMMIT WRITE NOWAIT 은 사용자와 상호작용이 없는 백그라운드 Application 에서 사용할 수 있다
- 실패 시 자동으로 재 시작할 수 있는 배치 프로그램(큐잉 매커니즘을 자체 구현한 프로그램) 등..
- 책 363 페이지 업무 사례 참조
비 분산 환경에서 PL/SQL 블록 내부 커밋
- 프로시저 내부에서 수행 하는 커밋은 NOWAIT 방식이다
- 사용자에게 프로시저 수행 완료를 반환하기 전에 마지막 생성 REDO 를 온라인 리두에 기록한다
- PL/SQL 블록 단위로는 영속성을 보장할 수 있다