트랜잭션이란?
아주 심플하게 보통 일의 최소 단위를 트랜잭션이라고 정의한다. 즉, 여러 개의 수정작업이 하나의 작업처럼 전부 처리되거나 아예 전부 처리가 안 되도록 하기 위한 것이다. 계좌이체를 할 때, 현금잔고를 확인하고 이체 비밀번호와 보안카드 코드값을 입력받아 최종 이체가 완료되는 순간까지를 트랜잭션 단위라고 할 수 있다.
트랜잭션은 다음과 같은 특징을 가진다.
- 원자성(Atomicity) : 더 이상 분해 불가능한 최소한의 업무단위를 말한다.
- 일관성(Consistency) : 트랜잭션이 실행을 성공적으로 완료했다면, 언제나 일관성 있는 데이터베이스 상태로 변환한다.
- 격리성(Isolation) : 트랜잭션이 실행 중에 생성하는 연산의 중간 결과는 다른 트랜잭션이 접근할 수 없다.
- 영속성(Durability) : 성공적으로 완료한 트랜잭션의 결과는 데이터베이스에 연속적으로 저장되어야 한다.
트랜잭션 고립화 수준
DBMS마다 구현방식이 다르다. 다만, ANSI/ISO SQL standard(SQL92)에서 정의하고 있는 트랜잭션 고립화 수준을 간단히 요약하면, 아래와 같다.
- 레벨0 (= Read Uncommitted)
-. 트랜잭션에서 처리 중인, 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용
-. Dirty Read, Non-Repeatable Read, Phantom Read 현상 발생
- 레벨1 (= Read Committed)
-. Dirty Read 방지 : 트랜잭션이 커밋되어 확정된 데이터만 읽는 것을 허용
-. 대부분의 DBMS가 기본모드로 채택하고 있는 일관성 모드
-. Non-Repeatable Read, Phantom Read 현상은 발생
-. DB2, SQL Server, Sybase의 경우 읽기 공유 Lock을 이용해서 구현. 하나의 레코드를 읽을 때 Lock을 설정하고 해당 레코드를 빠져 나가는 순간 Lock 해제
-. Oracle은 Lock을 사용하지 않고 쿼리 시작 시점의 Undo 데이터를 제공하는 방식으로 구현
- 레벨2 ( = Repeatable Read)
-. 선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때까지 후행 트랜잭션이 갱신하거나 삭제하는 것을 불허함으로써 같은 데이터를 두 번 쿼리했을 때 일관성 있는 결과를 리턴
-. 그러나 Phantom Read 현상은 여전히 발생
-. DB2, SQL Server 의 경우, 트랜잭션 고립화 수준을 Repeatable Read로 변경하면 읽은 데이터에 걸린 공유 Lock을 커밋할 때까지 유지하는 방식으로 구현
- 레벨3 ( = Serializable Read)
-. 선행 트랜잭션이 읽은 데이터를 후행 트랜잭션이 갱신/삭제/삽입을 막아준다. 따라서 완벽한 읽기 일관성 모드를 제공하며, 가장 강력한 고립화 수준이라 할 수 있다.
트랜잭션 고립화 수준의 각 레벨에서 나타나는 현상에 대해 알아보자.
- Drity Read(=Uncommitted Dependency)
-. 아직 커밋되지 않은 수정 중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생한다.
-. 대부분 DBMS에서 트랜잭션 고립화 수준 레벨1을 지향하기 때문에 Dirty Read 현상은 발생하지 않는다.
-. 동시성은 향상되지만, 일관성 유지에는 치명적이다.
- Non-Repeatable Read(= Inconsistent Analysis)
-. 한 트랜잭션 내에서 같은 쿼리를 두 번 수행할 때, 그 사이에 다른 트랜잭션이 값을 수정 또는 삭제함으로써 두 쿼리의 결과가 상이하게 나타나는 비일관성이 발생하는 것을 말한다.
- Phantom Read
-. 한 트랜잭션 안에서 일정범위의 레코드들을 두 번 이상 읽을 때, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다.
-. 트랜잭션 도중에 새로운 레코드가 삽입되는 것을 허용하기 때문에 나타나는 현상이다.
이상 트랜잭션 고립화 수준(Transaction Isoloation Levels)과 발생하는 현상을 매트릭스로로 정리하면 아래와 같다.
Isolation Level | Dirty Read | Non-repeatable Read | Phantom Read | Serialization Anomaly |
---|---|---|---|---|
Read uncommitted(Level 0) | Allowed, but not in PG | Possible | Possible | Possible |
Read committed(Level 1) | Not possible | Possible | Possible | Possible |
Repeatable read(Level 2) | Not possible | Not possible | Allowed, but not in PG | Possible |
Serializable(Level 3) | Not possible | Not possible | Not possible | Not possible |
★ PostgreSQL에서는 4단계 모두를 지원한다. 다만, Read Uncommitted 단계에서 PGSql은 Dirty Read를 허용하지 않기 때문에, 사실상 3단계로 정의할 수 있다.
PostgreSQL의 default 트랜잭션 고립화 수준 레벨은 Read Committed 이다. 트랜잭션 고립화 수준을 변경 하려면 아래와 같은 명령어를 사용해서 변경할 수 있다.
SET TRANSACTION transaction_mode [, ...]
SET TRANSACTION SNAPSHOT snapshot_id
SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...]
where transaction_mode is one of:
ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
READ WRITE | READ ONLY
[ NOT ] DEFERRABLE
고립화 수준을 Repeatable read로 바꾸고, 아래와 같이 두 트랜잭션을 수행하면 어떻게 되는지 테스트를 해보자.
--트랜잭션 고립화 수준을 한단계 위로 올리고, set transaction Isolation level Repeatable read write; --세션1의 트랜잭션 내용 --1) begin; -- 2) select * from dept where dept_cd = 'A001'; -- 세션2의 트랜잭션 전개 후, 아래의 쿼리가 진행될 때, lock 이 걸린다. --6) update dept set emp_num = emp_num + 10 where dept_cd = 'A001' commit; --세션 2의 트랜잭션 내용 --3) begin; --4) update dept set emp_num = emp_num + 10 where dept_cd = 'A001' --5) commit;
위 순서대로 실행하면, Lock 이 걸린다.
'Tech > Database' 카테고리의 다른 글
PostgreSQL - 날짜계산 (0) | 2018.07.06 |
---|---|
PostgreSQL - ABS, POWER, SQRT, POINT 함수 (2) | 2018.07.06 |
PostgreSQL - greatest, least, SIGN함수 (0) | 2018.07.03 |
PostgreSQL - COALESCE 함수 활용 (0) | 2018.07.03 |
PostgreSQL - 도메인 추출 쿼리 (0) | 2018.07.03 |
댓글