본문 바로가기

DB

[DB] 트랜잭션 (Transaction) – ACID 속성, 트랜잭션 격리 수준

🧩 트랜잭션이 필요한 이유: 'All or Nothing'의 약속

 

데이터베이스 제약 조건이 데이터의 '상태'를 지킨다면, 트랜잭션은 데이터를 변경하는 '행위'의 일관성을 보장한다.

 

가장 흔한 예로, 쇼핑몰에서 주문이 발생하면 최소 두 가지 작업이 함께 일어나야 한다.

  1. orders 테이블에 주문 내역을 INSERT
  2. products 테이블에서 상품 재고를 UPDATE

만약 1번 작업만 성공하고 2번 작업이 시스템 장애로 실패한다면 데이터베이스는 주문은 기록되었지만 재고는 줄어들지 않은,

즉, 일관성이 깨진 상태가 된다. 이는 재고 관리 실패와 고객 신뢰도 하락으로 이어지는 심각한 문제다.

 

트랜잭션은 이처럼 논리적으로 쪼갤 수 없는 여러 작업들을 하나의 묶음(Unit of Work)으로 다루어,

"전부 성공하거나, 하나라도 실패하면 전부 실패(All or Nothing)" 하도록 보장하는 핵심 안전장치다.

 


🧩 COMMIT과 ROLLBACK: 트랜잭션 제어하기

 

개발자는 다음 세 가지 명령어로 트랜잭션을 직접 제어할 수 있다.

  • START TRANSACTION: "지금부터 트랜잭션을 시작한다"고 데이터베이스에 선언한다.
  • COMMIT: 트랜잭션 내의 모든 작업이 성공적으로 완료되었을 때, 변경 사항을 데이터베이스에 영구적으로 저장(반영)한다.
  • ROLLBACK: 작업 중 문제가 발생했을 때, 트랜잭션 내에서 실행한 모든 변경 사항을 완전히 취소하고 시작 전 상태로 되돌린다.

MySQL은 기본적으로 모든 SQL 문 하나하나를 각각의 트랜잭션으로 간주하여, 성공하는 즉시 COMMIT하는 autocommit 모드가 활성화되어 있다. 따라서 여러 작업을 하나의 트랜잭션으로 묶으려면 반드시 START TRANSACTION을 명시적으로 사용해야 한다. 

 


✅ 트랜잭션의 4대 속성: ACID

 

데이터베이스 트랜잭션이 안전하게 동작하기 위해 반드시 다음 네 가지 속성(ACID)을 보장해야 한다.

이는 데이터 정합성안정성을 유지하기 위한 핵심 원칙이다.

 

  1. 원자성 (Atomicity)
    • 트랜잭션의 모든 작업이 모두 수행되거나, 전혀 수행되지 않아야 한다. (All or Nothing)
    • 트랜잭션 중간에 실패가 발생하면, 데이터베이스는 트랜잭션 시작 전 상태로 롤백해야 한다.
    • 예시:
      • 은행 계좌 이체 시 A 계좌에서 10만 원 출금 → B 계좌에 10만 원 입금
      • 원자성이 보장되지 않으면 A 계좌에서 돈만 빠져나가고 B 계좌에 입금되지 않는 불일치 발생
  2. 일관성 (Consistency)
    • 트랜잭션 수행 전과 수행 후, 데이터베이스는 항상 일관된 상태를 유지해야 한다.
    • 데이터베이스에 설정된 모든 규칙(제약 조건 등)이 항상 유지되어야 한다.
    • 예시:
      • 어떤 컬럼이 NOT NULL 제약을 가졌다면, 트랜잭션 완료 후에도 NULL 값이 들어가면 안 됨
      • 은행 계좌 합계가 1억이면, 트랜잭션 전후에도 전체 합계는 변하지 않아야 함
  3. 격리성 (Isolation)
    • 여러 트랜잭션이 동시에 실행될 때, 서로의 연산에 간섭하지 않도록 격리해야 한다.
    • 동시성 문제(Dirty Read, Non-Repeatable Read, Phantom Read 등)를 막기 위해 격리 수준이 필요하다.
    • 예시:
      • T1: A 계좌에서 10만 원 출금
      • T2: 동시에 A 계좌 잔액 조회
      • 격리성이 없으면 T2가 아직 커밋되지 않은 출금 결과를 조회할 수 있음 → 데이터 불일치 발생
  4. 지속성 (Durability)
    • 성공적으로 커밋된 트랜잭션의 결과는 시스템 오류가 발생해도 영구적으로 보존되어야 한다.
    • 트랜잭션 결과는 디스크에 기록되거나 로그에 보관되어 장애 시에도 복구 가능해야 한다.
    • 예시:
      • 계좌 이체 완료 후 서버가 다운되더라도, 재시작 시 커밋된 거래 내역은 반드시 반영되어 있어야 함

 


🚨 대표적인 동시성 문제 3가지

 

트랜잭션의 격리 수준이 낮으면 다음 세 가지 동시성 문제가 발생할 수 있다.

 

  1. Dirty Read (더티 리드)
    • 아직 커밋되지 않은 데이터다른 트랜잭션이 읽는 현상
    • 나중에 해당 트랜잭션이 롤백되면, 읽은 데이터는 실제로 존재하지 않게 됨
  2. Non-Repeatable Read (반복 불가능 읽기)
    • 같은 트랜잭션 내에서 같은 조건으로 조회했는데 값이 달라지는 현상
    • 다른 트랜잭션이 데이터를 수정하고 커밋했기 때문
  3. Phantom Read (유령 읽기)
    • 같은 트랜잭션 내에서 같은 조건으로 조회했는데 행(row)의 개수 자체가 달라지는 현상
    • 다른 트랜잭션이 데이터를 추가/삭제하고 커밋했기 때문

 


🧩 트랜잭션 격리 수준 (Isolation Level)

 

완벽한 격리성은 데이터의 정합성을 최고 수준으로 보장하지만, 여러 트랜잭션이 순서대로 처리되어야 하므로 동시성이 떨어져 성능이 저하될 수 있다. 데이터베이스는 이러한 정합성과 성능 사이의 트레이드오프를 개발자가 조절할 수 있도록 여러 단계의 격리 수준을 제공한다.

 

  1. READ UNCOMMITTED (커밋되지 않은 읽기)
    • 특징: 다른 트랜잭션에서 커밋하지 않은 데이터를 읽을 수 있음
    • 발생 가능한 문제:
      • Dirty Read ⭕
      • Non-Repeatable Read ⭕
      • Phantom Read ⭕
    • 장점: 동시성이 가장 높음 (락 거의 없음)
    • 단점: 데이터 정합성이 심각하게 깨질 수 있음
    • 실무 사용: 대용량 데이터의 실시간 집계나 통계 작업 (거의 사용하지 않음)
  2. READ COMMITTED (커밋된 읽기)
    • 특징: 다른 트랜잭션에서 커밋된 데이터만 읽을 수 있음
    • 발생 가능한 문제:
      • Dirty Read ❌
      • Non-Repeatable Read ⭕
      • Phantom Read ⭕
    • SELECT 시점마다 최신 커밋된 데이터를 읽음 → 같은 쿼리를 두 번 실행하면 결과가 달라질 수 있음
    • 실무 사용: Oracle, SQL Server 기본 설정, MySQL에서도 많이 사용됨
  3. REPEATABLE READ (반복 가능한 읽기)
    • 특징: 트랜잭션 내에서 같은 조건으로 같은 데이터를 조회하면 항상 동일한 결과를 얻음
    • 발생 가능한 문제:
      • Dirty Read ❌
      • Non-Repeatable Read ❌
      • Phantom Read ⭕
    • 실무 사용: MySQL(InnoDB) 기본 설정
    • MySQL InnoDB 엔진은 MVCC(다중 버전 동시성 제어)Gap Lock을 통해 대부분의 팬텀 리드도 방지해줌
  4. SERIALIZABLE (직렬화 가능)
    • 특징: 트랜잭션들을 직렬(순차) 실행하는 것과 동일한 효과 → 완전한 격리성 보장
      • 발생 가능한 문제:
        • Dirty Read ❌
        • Non-Repeatable Read ❌
        • Phantom Read ⭕
    • 단점: 락이 많이 걸려 성능 저하 심각
    • 실무 사용: 데이터 정합성이 절대적으로 중요한 경우에만 사용 (거의 안 씀)

 

특별한 이유가 없다면 MySQL의 기본 격리 수준인 REPEATABLE READ를 그대로 사용하는 것이 좋다.
이는 대부분의 환경에서 정합성과 성능의 합리적인 균형을 제공한다.

 

'DB' 카테고리의 다른 글

[DB] ORDER BY에서 별칭을 사용할 때 주의할 점  (0) 2026.02.25
[DB] 데이터 무결성 (Data Integrity), 제약 조건 (Constraints)  (0) 2025.09.21
[DB] 인덱스 (Index)  (2) 2025.09.21
[DB] 뷰 (VIEW)  (1) 2025.09.19
[DB] CASE 문  (0) 2025.09.19