트랜잭션 격리성과 데드락 해결

김대은·2026년 8월 9일

트랜잭션이란?

트랜잭션 : 데이터베이스의 상태를 변화시키기 위해서 수행하는 작업의 단위를 뜻한다.

데이터베이스의 상태를 변화 시킨다는 것은 무엇을 말하는 걸까?

간단하게 말해서 SQL을 이용해서 데이터베이스를 접근 하는 것을 의미한다.

  • SELECT
  • INSERT
  • DELETE
  • UPDATE

그러나 작업의 단위는 질의어 한문장이 아니라는 점이다.
작업단위는 많은 질의어 명령문들을 사람이 정하는 기준에 따라 정하는 것을 의미한다.


1. 1단계: 글 쓰기 (Insert 단계)

  • 사용자의 행동: 사용자가 게시판에 글을 작성하고 '올리기' 버튼을 누릅니다.
  • 데이터베이스 작업: 데이터베이스는 이 글을 저장하기 위해 Insert(삽입) 명령어를 사용해 새 데이터를 추가합니다.

2. 2단계: 최신 화면 보여주기 (Select 단계)

  • 사용자의 행동: 글이 올라간 후, 사용자는 자동으로 업데이트된 게시판 화면을 보게 됩니다.
  • 데이터베이스 작업: 방금 쓴 글을 포함해 최신 목록을 보여주기 위해, 데이터를 다시 꺼내오는 Select(조회) 명령어를 실행합니다.

3. 3단계: 하나로 묶기 (Transaction 단계)

  • 핵심 개념: 글을 쓰고(Insert) 최신 화면을 보는 것(Select)은 분리되면 안 되는 '하나의 세트'입니다.
  • 정의: 이렇게 하나의 목적을 이루기 위해 묶어놓은 작업 단위를 트랜잭션(Transaction)이라고 합니다. 이 설계를 잘해야 데이터가 꼬이지 않고 안전하게 관리됩니다.

트랜잭션의 특징

트랜잭션이 안전하게 처리되기 위해서는 다음 4가지 특징(ACID)을 만족해야 한다.

  • 원자성 (Atomicity)
  • 일관성 (Consistency)
  • 독립성/격리성 (Isolation)
  • 지속성 (Durability)

1. 원자성 (Atomicity)

원자성은 트랜잭션이 데이터베이스에 모두 반영되던가, 아니면 전혀 반영되지 않아야 한다는 것이다.
작업 도중 오류가 발생하면 모든 작업을 취소하고 이전 상태로 되돌려야 하며(Rollback), 모든 작업이 성공했을 때만 결과를 최종 확정한다(Commit).

2. 일관성 (Consistency)

일관성은 트랜잭션이 성공적으로 완료되면 데이터베이스가 언제나 일관성 있는 상태를 유지해야 한다는 것이다.
데이터베이스가 정한 제약 조건이나 규격을 위반하는 트랜잭션은 실행 도중 중단되고 취소된다.

3. 독립성/격리성 (Isolation)

독립성은 둘 이상의 트랜잭션이 동시에 실행될 때, 서로의 작업에 영향을 주지 않아야 한다는 것이다.
하나의 트랜잭션이 진행 중일 때는 다른 트랜잭션이 해당 데이터에 접근하거나 수정할 수 없도록 제어해야 한다.

4. 지속성 (Durability)

지속성은 성공적으로 완료된 트랜잭션의 결과가 데이터베이스에 영구적으로 반영되어야 한다는 것이다.
시스템에 장애나 오류가 발생하더라도 이미 완료된 작업 결과는 손실되지 않고 유지되어야 한다.

트랜잭션 격리성 (Transaction Isolation)

트랜잭션의 격리성은 둘 이상의 트랜잭션이 동시에 실행될 때 서로의 연산에 개입하지 못하도록 제어하는 성질이다.

데이터베이스는 트랜잭션의 접근 레벨(격리 수준)을 설정할 수 있으며, 격리성을 강하게 처리할 수도 있고 반대로 약하게 처리할 수도 있다. 격리성을 너무 강하게 설정하면 동시 처리 성능이 떨어지고, 너무 약하게 설정하면 데이터의 정합성이 깨지는 문제가 발생한다.


격리성 낮음으로 인해 발생할 수 있는 문제점

격리 수준이 낮을 때 발생하는 이상 현상은 대표적으로 Dirty Read, Non-Repeatable Read, Phantom Read 3가지가 있다.

1. Dirty Read

다른 트랜잭션에 의해 수정되었지만 아직 커밋되지 않은 데이터를 읽는 현상이다.
예를 들어 Transaction 1이 데이터를 수정했으나 정상 처리되지 않고 롤백(Rollback)되는 경우가 발생할 수 있다. 이때 해당 값을 미리 읽어간 Transaction 2는 존재하지 않는 잘못된 값을 바탕으로 로직을 처리하는 상태에 놓이게 된다.

2. Non-Repeatable Read

한 트랜잭션 내에서 같은 Key를 가진 1개의 Row(단일 레코드)를 두 번 읽었을 때, 그 사이에 값이 변경되거나 삭제되어 결과가 다르게 나타나는 현상이다.
Transaction 1이 조회 작업을 진행하는 중간에 Transaction 2가 해당 데이터를 수정하고 커밋하면, Transaction 1이 다시 데이터를 읽었을 때 이전과 다른 값이 조회된다.

3. Phantom Read

한 트랜잭션 내에서 같은 조건의 쿼리를 두 번 수행했을 때, 첫 번째 쿼리에서는 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 새롭게 나타나는 현상이다.
Transaction 1이 범위 조회를 하는 도중 Transaction 2가 해당 범위 내에 새 데이터를 추가(Insert)하고 커밋하면 발생한다.

Non-Repeatable Read vs Phantom Read 차이점

  • Non-Repeatable Read: 단일 Row의 데이터 값이 수정/삭제되어 결과가 변하는 것이다.
  • Phantom Read: 여러 건을 요청하는 범위 조회에서 새로운 데이터가 추가되어 결과 건수가 변하는 것이다.

지정할 수 있는 격리 수준 (Isolation Level)

아래 4개의 격리 수준은 ANSI/ISO SQL 표준(SQL92)에서 정의한 내용이며, 위에서 아래로 갈수록 격리 수준이 높아진다.

1. Read Uncommitted (최하 수준)

  • 가장 낮은 격리 수준으로, 트랜잭션에서 변경된 내용이 커밋되지 않더라도 다른 트랜잭션에서 읽을 수 있다.
  • 발생 문제점: Dirty Read, Non-Repeatable Read, Phantom Read가 모두 발생할 수 있다.
  • 특징: 데이터 정합성이 보장되지 않지만, 동시성이 가장 높다.

2. Read Committed

  • 트랜잭션이 커밋을 완료한 데이터만 다른 트랜잭션에서 읽을 수 있다.
  • 발생 문제점: Dirty Read는 방지할 수 있지만, Non-Repeatable Read와 Phantom Read는 여전히 발생할 수 있다.
  • 특징: 동시성은 Read Uncommitted보다 낮아지지만 여전히 높은 편이며, 많은 RDBMS의 기본 격리 수준으로 사용된다.

3. Repeatable Read

  • 트랜잭션 내에서 동일한 쿼리를 실행하면 항상 동일한 결과가 나온다.
  • 발생 문제점: Non-Repeatable Read는 방지할 수 있지만, 여전히 Phantom Read는 발생할 수 있다. (단, MySQL InnoDB 등 일부 엔진에서는 별도 메커니즘을 통해 Phantom Read까지 방지하기도 한다.)
  • 특징: 동시성은 Read Committed보다 낮아지지만 중간 정도의 수준을 유지한다.

4. Serializable Read (최고 수준)

  • 가장 높은 격리 수준으로, 모든 트랜잭션들이 직렬화되어 순차적으로 실행된다.
  • 발생 문제점: Dirty Read, Non-Repeatable Read, Phantom Read 등 모든 이상 현상이 발생하지 않는다.
  • 특징: 데이터의 정합성을 완벽하게 보장하지만, 동시에 여러 트랜잭션이 실행될 때 차례대로 처리되어야 하므로 동시성과 성능이 가장 낮아진다.
격리 수준 (Isolation Level)Dirty ReadNon-Repeatable ReadPhantom Read
Read Uncommitted (최하 수준)발생발생발생
Read Committed방지발생발생
Repeatable Read방지방지발생 *
Serializable Read (최고 수준)방지방지방지

교착 상태(Deadlock) 해결 방법

교착 상태(Deadlock)란 둘 이상의 프로세스나 트랜잭션이 서로가 점유하고 있는 자원을 대기하며 무한히 기다리는 상태를 말한다.

교착 상태를 해결하는 방법은 크게 무시(Ignore), 예방(Prevention), 회피(Avoidance), 탐지 및 복구(Detection & Recovery) 4가지로 나뉜다.


1. 교착 상태 무시 (Deadlock Ignore)

교착 상태 발생 빈도가 낮을 경우, 별도의 처리 알고리즘을 수행하는 대신 교착 상태가 발생하도록 방치하고 필요 시 시스템을 재부팅하는 방식이다.
Unix, Windows 등 대부분의 일반 운영체제에서 채택하고 있다.


2. 교착 상태 예방 (Deadlock Prevention)

교착 상태의 4가지 발생 조건 중 하나 이상을 차단하여 교착 상태 발생을 방지하는 방법이다.

  • 상호 배제(Mutual Exclusion) 부정: 공유 가능한 자원을 사용한다.
  • 점유 및 대기(Hold and Wait) 부정: 프로세스 실행 시 필요한 모든 자원을 한 번에 할당하거나, 자원을 점유하지 않은 상태에서만 추가 자원을 요청하도록 제약한다.
  • 비선점(No Preemption) 부정: 요청한 자원을 할당받지 못할 경우, 기존에 점유하던 자원을 반납하고 대기하도록 자원 선점을 허용한다.
  • 순환 대기(Circular Wait) 부정: 모든 자원에 순서를 부여하고, 해당 순서에 따라 자원을 요청하도록 제약한다.

3. 교착 상태 회피 (Deadlock Avoidance)

자원 요청 시 시스템이 안전 상태(Safe State)를 유지할 수 있는 경우에만 자원을 할당하는 방법이다.

주요 개념

  • Safe State: 모든 프로세스가 정상 종료될 수 있는 자원 할당 순서(Safe Sequence)가 존재하는 상태이다.
  • Unsafe State: Safe Sequence가 존재하지 않는 상태로, 교착 상태로 전이될 가능성이 있다.

회피 알고리즘

  1. 자원 할당 그래프 알고리즘 (Resource-Allocation Graph Algorithm)
  • 단일 자원 인스턴스 환경에서 사용한다.
  • 예약 간선(Claim Edge)을 활용하여 자원 할당 시 주기(Cycle)가 형성되지 않는 경우에만 자원을 할당한다.
  1. 은행원 알고리즘 (Banker's Algorithm)
  • 다중 자원 인스턴스 환경에서 사용한다.
  • 각 프로세스의 최대 자원 요구량을 미리 파악하고, 자원 할당 후에도 Safe State가 유지되는 경우에만 할당한다.

4. 교착 상태 탐지 및 복구 (Detection & Recovery)

교착 상태 발생을 허용하고, 주기적인 탐지 알고리즘을 통해 교착 상태를 확인한 후 복구하는 방식이다.

탐지 알고리즘 (Detection)

  • 대기 그래프 (Wait-for Graph): 단일 자원 인스턴스 환경에서 자원 할당 그래프를 프로세스 간의 대기 관계 그래프로 변환하여 주기(Cycle) 발생 여부를 탐지한다.
  • 은행원 알고리즘: 다중 자원 인스턴스 환경에서 프로세스의 요청(Request) 자원량을 기준으로 Unsafe State 여부를 탐지한다.

복구 방식 (Recovery)

  1. 프로세스 종료
  • 교착 상태에 빠진 프로세스를 일괄 중지하거나, 교착 상태가 해제될 때까지 순차적으로 하나씩 중지한다.
  1. 자원 선점
  • 교착 상태에 있는 프로세스의 자원을 강제로 선점하여 다른 프로세스에 할당한다.
  • 대상 프로세스 선정: 자원 선점으로 인한 영향이 가장 적은 프로세스를 선택한다.
  • 롤백(Rollback): 선점된 프로세스는 이전 상태로 되돌리고 재시작한다.
  • 기아 상태 방지: 동일 프로세스가 반복해서 선점되지 않도록 우선순위를 조정한다.

0개의 댓글