티스토리 뷰

트랜잭션이란?
- 영어로는 Transaction이라고 합니다.
- 사전적 의미로는 거래, 매매, 처리(과정) 이라는 뜻을 가집니다.
- IT 분야의 개념으로는 "하나의 작업을 수행하기 위해 필요한 DB의 연산들을 모아놓은 것으로 DB에서 논리적인 작업의 단위" 라고 말합니다.
RollBack
트랜잭션 중 오류가 발생하면, 지금까지 진행 된 작업은 전부 취소하고 DB 데이터를 이전 상태로 되돌립니다.
Commit
트랜잭션 내 모든 작업이 정상적으로 완료되었음을 DB에 알리고, 변경사항을 DB에 영구 저장합니다.

예시) 쇼핑몰에서 고객이 상품을 주문하면?
- 주문 저장
- 결제
- 재고 차감
- 포인트 적립
실패하면 전체 작업이 무효가 되어야 하고 주문이 성공하면 모든 작업이 DB에 저장됩니다.
트랜잭션의 4가지 속성 ACID
Atomicity (원자성)
- 트랜잭션 내 모든 작업이 모두 성공하거나, 모두 실패하거나
- 트랜잭션 내 작업이 1개라도 실패하면 모두 실패 처리를 해야 합니다.
- 김영웅이 이지금에게 20만원 계좌 이체 한다고 할 때 김영웅의 계좌에서 -20만원 이지금의 계좌에서 +20만원 연산이 성공해야합니다.

Consistency (일관성)
- 트랜잭션 실행 전과 실행 후의 데이터는 항상 정합성 있는 상태여야 한다.
- 트랜잭션 전후의 데이터는 항상 제약 조건과 비즈니스 규칙을 만족해야합니다.
- 김영웅과 이지금의 자산이 총 150만원 이였다면 계좌 이체 후에도 트랜잭션 후에도 변함이 없어야 합니다.
또는, 가지고 있는 돈보다 더 많은 돈을 이체하려고 한다면 Rule을 위반 했기 때문에 실패처리가 됩니다.

Isolation (격리성)
- 여러 트랜잭션이 동시에 수행돼도 서로 영향을 주지 않아야 합니다.
- Concurrency Control(동시성 제어)의 주된 목표는 Isolation 입니다.
- DBMS는 여러 종류의 Isolation Level(격리 레벨)을 제공합니다.
격리 레벨은 아래에 더 추가적으로 알아보도록 하겠습니다. - 김영웅이 이지금에게 20만원을 송금하는 순간에 제 3자가 50만을 송금하면 어떻게 될까요?
이지금의 계좌를 +20만원 커밋을 안했는데 그 사이에 누가 50만원 송금을 하면 이전 돈에 +50만원이 되니 20만원은 날라가지 않을까요?
→ 이것을 깊게 다룬 것이 DBSM마다 다르게 동작하는 격리 수준을 아래에서 배워보도록 하겠습니다.

Durability (지속성)
- 트랜잭션이 커밋되면, 시스템 장애가 나도 결과는 DB에 반드시 저장되어야 합니다.
- DB에 영구적으로 저장한다는 의미는 비휘발성 메모리(HDD, SSD)에 저장하는 것을 의미합니다.

정리
| 속성 | 의미 | 계좌 이체 예시 |
| Atomicity (원자성) | 전부 성공 or 전부 실패 | A에서 돈이 나갔는데 B에 입금 안되는 경우는 없음. |
| Consistency (일관성) | 트랜잭션 전후 무결성 보장 | A, B의 총 자산은 변하지 않아야 함. |
| Isolation (격리성) | 동시에 실행되어도 간섭 없음 | 제 3자가 잔액을 조회해도 이체해도 안전. |
| Durability (지속성) | 커밋되면 영구 보존 | 이체 이후 서버 장애가 나도 결과는 유지됨. |
트랜잭션에서 문제 이상 현상
백엔드 개발자라면 앞으로 만나게될 상황이고 트랜잭션 격리레벨을 알기 위해서 알아두셔야합니다.
Dirty Read (더러운 읽기)
- 현재 트랜잭션이 다른 트랜잭션의 커밋되지 않은 데이터를 읽는 상황
- 즉, 아직 확정되지 않은 데이터를 읽었다가, 그 트랜잭션이 Rollback되면 엉더리 데이터를 읽는 이상한 상황입니다.
- @예시 시나리오
- Transaction1 : A가 B에게 40만원 이체
- Transaction2 : B는 이체된 값에 +20만원 이체
- Transaction1 : 이체 오류로 인해 Rollback
- Transaction2 : Rollback 되기 전으로 처리 되었기 때문에 +20만원 꽁돈 ^_^
- 문제점 : 커밋되지 않은 데이터를 읽었기 때문에 데이터 정합성이 깨집니다.
Nonrepeatable Read (반복 불가능한 읽기)
- 하나의 트랜잭션 안에서 같은 조건으로 두번 읽었는데 다른 값으로 조회되는 상황
- 즉, 다른 트랜잭션이 시작 전에 읽었다가 그 트랜잭션이 Commit을 하고 다시 읽으면 다른 값으로 조회되는 이상한 상황입니다.
- @예시 시나리오
- Transaction1 : A가 B의 계좌 잔액을 조회 (100만원)
- Transaction2 : B가 자기 계좌에 20만원 이체하고 커밋
- Transaction1 : A가 B의 계좌 잔액을 다시 조회 (120만원) → 비즈니스 상 데이터가 달라서 뭘 봐야할지 알수 없음 ^_^
- 문제점 : 비즈니스 로직 오류를 유발할 수 있습니다.
Phantom Read (팬텀 읽기)
- 같은 조건으로 두번 읽었는데 첫 번째 읽었을 때와 다르게 새로운 데이터가 생기는 현상
- 즉, 다른 트랜잭션 시작 전에 읽었다가 그 트랜잭션이 Commit을 하고 다시 읽으면 값이 하나더 생기는 이상한 상황입니다.
- @예시 시나리오
- Transaction1 : 30세 이상 유저만 검색 조회했을 경우 100명
- Transaction2 : 35세인 뉴사용자가 생겨 데이터 추가되고 Commit
- Transaction1 : 다시 같은 조건으로 30세 이상 유저만 검색 조회 했을 경우 101명으로 조회
- 문제점 : 데이터 개수가 일관 되지 않습니다.

이 이상현상들을 모두 발생하지 않게 만들 수 있지만, 제약사항이 많아져서 동시 처리 가능한 트랜잭션 수가 줄어서 결국 DB의 처리량이 낮아지기 때문에 성능이 낮아진다고 할 수 있습니다.
트랜잭션 격리 레벨, 격리 수준
https://www.postgresql.org/docs/17/transaction-iso.html
13.2. Transaction Isolation
13.2. Transaction Isolation # 13.2.1. Read Committed Isolation Level 13.2.2. Repeatable Read Isolation Level 13.2.3. Serializable Isolation Level The SQL standard …
www.postgresql.org

PostgreSQL의 모든 격리 수준은 MVCC + Snapshot을 기반으로 합니다.
스냅샷은 트랜잭션 별로 메모리상의 구조체에 저장됩니다.
그래서 Commit할 때 변경된 데이터를 저장하고 Rollback할 때는 스냅샷을 다 날려버리게 되는 것입니다.
MVCC는 다음 포스팅에 ^_^
Read Uncommitted
- PostgreSQL에서는 지원되지 않기 때문에 내부적으로 Read Commited로 처리됩니다.
- 즉, 다른 트랜잭션에서 아직 커밋되지 않은 데이터를 읽을 수 없습니다.
Read committed (기본)
- PostgreSQL에서 기본 격리 수준입니다.
- 쿼리 실행 시점에 커밋된 데이터만 읽습니다.
- 즉, 다른 트랜잭션에서 아직 커밋되지 않은 데이터를 읽을 수 없습니다.
- 일어날 수 있는 현상은 Nonrepeatable Read(반복 불가능한 읽기)와 Phantom Read(팬텀 리드)가 나타날 수 있습니다.
Repeatable read
- PostgreSQL에서 지원되는 격리 수준입니다.
- 트랜잭션 시작 시점의 스냅샷 기준으로 일관된 데이터를 반환합니다.
- 즉, 데이터가 변경되더라도 트랜잭션 내에서는 동일한 값을 읽습니다. 하지만 새로운 데이터 삽입은 영향을 줄 수 있습니다.
- 일어날 수 있는 현상은 Phantom Read(팬텀 리드)가 나타날 수 있습니다.
Serializable
- PostgreSQL에서 가장 높은 격리 수준을 가지고 있습니다.
- 트랜잭션이 직렬화된 것처럼(순서대로) 동작하도록 보장합니다.
- 동시성 충돌 시 예외를 발생시키며, 충돌을 자동으로 감지하고 롤백할 수 있습니다.
- 일어날 수 있는 현상은 없으며 대신 동시에 처리하는 DB 능력은 떨어 질 것입니다.

감사합니다.
'데이터 베이스 > 🐘PostgreSQL' 카테고리의 다른 글
| [PostgreSQL] 로컬을 넘어 운영으로: Master-Slave 복제 3대 장애 시나리오와 방어책 (0) | 2026.04.20 |
|---|---|
| [PostgreSQL] 대규모 트래픽을 견디는 아키텍처 : Primary-Replica 구축부터 WAL 동기화까지 (1) | 2026.04.15 |
| [PostgreSQL] 운영에 필요한 로그 세팅 6가지 (0) | 2025.05.06 |
| [PostgreSQL] Lock 완전 정복: 성능 저하 없이 정합성 지키기 (0) | 2025.04.28 |
- Total
- Today
- Yesterday
- 그리디
- Front
- 알고리즘
- 네트워크
- JPA 페이징
- aws
- 깃허브 액션
- 데이터 베이스
- BFS
- 코딩테스트
- 개발
- 멀티모듈
- 디자인패턴
- Flutter
- CI/CD
- spring
- 프로세스
- 개발자
- Spring Security
- JavaScript
- 개발블로그
- Primary-Replica
- 트랜잭션
- Fetch
- 장애대응
- java
- DBeaver
- 시간 객체
- 카카오 로그인
- 개발환경
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |