이 글에선 트랜잭션의 격리 수준을 간단히 소개하고 PostgreSQL에서 사용하는 방법을 알아본다.

 

📌 격리수준의 종류

> READ UNCOMMITTED

트랜잭션의 변경사항을 Commit하지 않아도 다른 트랜잭션에서 읽어들일 수 있음

dirty read 현상이 발생할 수 있다. (완료되지 않은 데이터를 다른 트랜잭션에서 접근하는 것)

> READ COMMITTED (기본값)

트랜잭션은 Commit한 데이터만 읽어들임

non repeatable read 현상이 발생할 수 있다. (경우에 따라서 같은 읽기 명령이라도 결과가 다를 수 있음)

> REPEATABLE READ

트랜잭션이 항상 자신이 생성되기 전에 변경된 데이터만 읽어들임

Update Lock

phantom read 현상이 발생할 수 있다. (삭제/추가 잠금이 없기 때문에, 읽었던 데이터가 사라지거나 다른게 추가되는 상황이 나타날 수 있다.)

> SERIALIZABLE

동시성을 포기하고 안전성을 잡은 방법.

Update/Delete/Insert Lock

> SNAPSHOT

데이터를 모조리 복사해서 수정 후, 병합하는 방식 (병합 시 충돌 확인을 함.)

아래에 자세한 설명이 나와있다.

https://www.geeksforgeeks.org/what-is-snapshot-isolation/

 

더 자세한 내용은 아래 참고

- https://nesoy.github.io/articles/2019-05/Database-Transaction-isolation

- https://www.postgresql.org/docs/current/sql-set-transaction.html

📌 PostgreSQL에서 격리수준을 설정하는 방법

쿼리는 다음과 같다.

SET TRANSACTION ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }

실제로 동작하는건 3개로, READ UNCOMMITTED는 READ COMMITTED으로 대체된다.

 

SNAPSHOT은 좀 복잡하게 설정해야 한다.

아래와 같이 해야하는데, 스냅샷 id는 pg_export_snapshot()으로 구해야 한다.

SET TRANSACTION SNAPSHOT 스냅샷id

 

예제는 아래와 같다.

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT pg_export_snapshot();
    pg_export_snapshot
    ---------------------
    00000003-0000001B-1  -- 이게 SNAPSHOT id
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET TRANSACTION SNAPSHOT '00000003-0000001B-1';

 

SNAPSHOT을 사용할때, 트랜잭션 격리수준은 SERIALIZABLE이나 REPEATABLE READ를 써야 한다. (READ COMMITTED을 쓰면 하나의 명령어가 수행될 때마다 하나의 SNAPSHOT을 생성한다고 함)

2jun0