본문 바로가기
Tech/Database

Transaction의 이해 - PostgreSQL

by Augustine™ 2018. 7. 4.
반응형

트랜잭션이란?

아주 심플하게 보통 일의 최소 단위를 트랜잭션이라고 정의한다. 즉, 여러 개의 수정작업이 하나의 작업처럼 전부 처리되거나 아예 전부 처리가 안 되도록 하기 위한 것이다. 계좌이체를 할 때, 현금잔고를 확인하고 이체 비밀번호와 보안카드 코드값을 입력받아 최종 이체가 완료되는 순간까지를 트랜잭션 단위라고 할 수 있다.

트랜잭션은 다음과 같은 특징을 가진다. 

  • 원자성(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 LevelDirty ReadNon-repeatable ReadPhantom ReadSerialization Anomaly

Read uncommitted(Level 0)

Allowed, but not in PGPossiblePossiblePossible
Read committed(Level 1)Not possiblePossiblePossiblePossible
Repeatable read(Level 2)Not possibleNot possibleAllowed, but not in PGPossible

Serializable(Level 3)

Not possibleNot possibleNot possibleNot 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

댓글