[Lock-4][Optimization] Redo/Undo 로그와 MVCC 원리

2025. 12. 25. 12:07·Database/MySQL

1. 들어가며: 데이터베이스는 변경 사항을 어떻게 기억하는가?

 데이터베이스의 핵심 원칙 중 하나는 지속성(Durability)이다. 즉, 한번 커밋된 데이터는 시스템에 어떤 장애가 발생하더라도 반드시 보존되어야 한다.

 

 가장 직관적인 방법은 데이터가 변경될 때마다 즉시 디스크에 저장하는 것이다. 하지만 이 방식은 현실적인 성능 한계를 가진다. 디스크는 메모리에 비해 입출력 속도가 매우 느리고, 특히 랜덤 I/O가 발생하면 처리 시간이 급격히 증가한다. 변경이 발생할 때마다 디스크에 직접 쓰기를 수행한다면 커밋 시간이 길어지고, 동시에 처리할 수 있는 트랜잭션 수 역시 크게 줄어들게 된다.

 

 이 문제를 해결하기 위해 InnoDB는 데이터를 즉시 디스크에 반영하지 않는다. 대신 변경 사항을 먼저 기록해 두고, 나중에 디스크에 반영하는 방식, 즉 WAL(Write-Ahead Logging)을 사용한다. 이 구조에서 핵심적인 역할을 수행하는 것이 Redo Log와 Undo Log다.

 


2. InnoDB의 핵심 메커니즘: Redo 로그와 Undo 로그

구분 Redo 로그 (포스트잇) Undo 로그 (백업본)
비유 변경 사항을 빠르게 메모함 수정 전 데이터를 복사해둠
목적 시스템 장애 시 데이터 복구 (지속성) 트랜잭션 취소 시 복원 및 격리성 유지
데이터 "어떻게 변경했는가?" (New Data) "원래 데이터가 무엇인가?" (Old Data)
삭제 시점 데이터가 디스크에 완전히 반영된 후 관련 트랜잭션이 종료(COMMIT)된 후 (MVCC 참조 종료 시)

 InnoDB의 내부 동작은 “노트를 관리하는 사람의 업무 방식”에 비유하면 이해하기 쉽다. 모든 정보가 깔끔하게 정리된 마스터 노트가 있다고 가정하자. 이 노트는 정확하지만, 내용을 수정하거나 다시 작성하는 데 시간이 오래 걸린다. 반면 회의 중에는 중요한 내용이 빠르게 쏟아지기 때문에, 매번 노트를 다시 쓰는 것은 비효율적이다.

2.1. Redo 로그 — 포스트잇 (장애 복구용)

 이럴 때 사람은 보통 포스트잇에 먼저 내용을 적어 둔다. InnoDB에서 이 포스트잇에 해당하는 것이 Redo Log다. 데이터가 변경되면 InnoDB는 변경된 결과를 곧바로 디스크에 쓰지 않고, 먼저 Redo Log에 기록한다. 이 기록은 매우 빠르게 이루어지며, 트랜잭션이 커밋되면 “이 변경 사항은 반드시 유지되어야 한다”는 의미를 갖게 된다.

 만약 디스크에 반영되기 전에 서버가 갑자기 종료되더라도 문제는 없다. 재시작 시 InnoDB는 Redo Log를 확인하여, 디스크에 반영되지 못한 변경 사항들을 다시 적용할 수 있기 때문이다. 이처럼 Redo Log는 성능을 확보하면서도 지속성을 보장하기 위한 장치다.

2.2. Undo 로그 — 백업본 (롤백 및 격리용)

 하지만 변경을 기록하는 것만으로는 충분하지 않다. 회의 내용을 잘못 적었거나, 회의 자체를 취소해야 하는 상황도 발생할 수 있다. 그래서 철저한 사람이라면 회의를 시작하기 전에 기존 노트를 복사해 백업본을 만들어 둔다. 이 백업본이 바로 Undo Log다. InnoDB는 데이터를 수정하기 직전에, 기존 값을 Undo Log에 저장한다. 트랜잭션이 롤백되면 이 Undo Log를 참조해 데이터를 원래 상태로 되돌릴 수 있다. 트랜잭션이 정상적으로 커밋되었다면, 해당 Undo Log는 더 이상 롤백 용도로는 필요 없어지게 된다.  Undo Log는 단순히 롤백을 위한 장치에 그치지 않는다. 나중에 설명할 격리 수준과 MVCC에서는, 다른 트랜잭션에게 “과거의 데이터”를 보여주는 역할도 수행한다.


3. 격리성 수준과 로그의 상세 매커니즘

격리 수준(Isolation Level)은 단순히 “얼마나 엄격한가”의 문제가 아니다. InnoDB 관점에서 보면, “조회 시 어떤 버전의 데이터를 선택할 것인가”에 대한 정책 차이다. 이때 각 격리 수준은 Redo 로그와 Undo 로그를 서로 다르게 활용한다. 이를 이해하기 위해 다음 상황을 가정해 보자.

1) 초기 상태: id = 1, balance = 1000
2) 트랜잭션 A가 해당 계좌의 잔액을 500으로 변경
3) 동시에 트랜잭션 B가 같은 데이터를 조회

3.1. Read Uncommitted: Redo 로그의 즉각적인 노출

이 레벨에서는 격리를 위한 별도의 장치가 거의 작동하지 않는다.

  • 동작 원리: 트랜잭션 A가 데이터를 수정하면, 해당 변경 사항은 즉시 메모리와 Redo 로그(포스트잇)에 기록된다. 이때 Read Uncommitted 수준의 트랜잭션 B가 조회를 요청하면, 커밋 여부와 상관없이 현재 메모리 및 Redo 로그에 적힌 최신 값(500)을 그대로 읽어온다.
  • Dirty Read의 이유: 트랜잭션 A가 최종적으로 ROLLBACK을 수행하면 Redo 로그의 내용은 무효화되고 Undo 로그를 통해 1000으로 복구되지만, 이미 B는 무효화될 값인 500을 읽어간 상태가 된다.

3.2. Read Committed: Undo 로그를 통한 '커밋된 버전' 찾기

가장 일반적으로 사용되는 이 레벨은 Undo 로그(백업본)를 적극적으로 활용한다.

  • 동작 원리: 트랜잭션 B가 조회를 시도할 때, 수정 중인 데이터의 행(Row)에 '커밋되지 않은 변경'이 있음을 감지하면, 실제 데이터가 아닌 Undo 로그에 저장된 백업본을 찾아가서 읽는다.
  • 결과: 트랜잭션 A가 500으로 수정한 후 아직 커밋하지 않았다면, B는 Undo 로그에 보관된 '수정 전 데이터(1000)'를 읽음으로써 Dirty Read를 방지한다. 오직 A가 커밋을 완료하여 백업본이 갱신되어야만 B는 최신값(500)을 볼 수 있게 된다.

3.3. Repeatable Read: 첫 번째 Undo 로그 스냅샷의 고정

MySQL의 기본 모드인 이 레벨은 '한 번 본 데이터는 끝까지 유지한다'는 원칙을 지킨다.

  • 동작 원리: 트랜잭션 B가 첫 번째 SELECT를 수행하는 시점에 Consistent Read View(스냅샷)를 생성한다. 이후 트랜잭션 A가 데이터를 500으로 수정하고 커밋까지 완료하더라도, B는 자신이 처음에 잡았던 그 시점의 Undo 로그 버전을 계속해서 참조한다.
  • 결과: 트랜잭션 B 내에서는 몇 번을 조회해도 항상 1000이라는 동일한 결과를 얻는다. 이는 여러 트랜잭션이 각자의 버전을 가진다는 의미에서 MVCC(Multi-Version Concurrency Control)의 핵심이 된다.

4. MVCC(Multi-Version Concurrency Control)의 원리

MVCC(다중 버전 동시성 제어)는 하나의 레코드에 대해 여러 개의 버전이 동시에 존재하는 것처럼 관리하는 기술이다.

4.1. 동작 방식

 각 트랜잭션은 고유한 번호를 가지며, 데이터를 읽을 때 자신의 트랜잭션 번호보다 낮은(즉, 자신이 시작되기 전에 커밋된) 버전의 데이터를 Undo 로그에서 찾아 읽는다. 이를 통해 읽기 작업이 쓰기 작업을 방해하지 않고(Lock-free Read) 높은 동시성을 유지할 수 있다.

4.2. 주의 사항: 긴 트랜잭션의 위험성

 트랜잭션이 종료되지 않고 길게 유지되면, 해당 트랜잭션이 참조할 가능성이 있는 모든 Undo 로그 버전을 삭제하지 못하고 유지해야 한다. 이는 시스템 저장 공간의 급격한 소모와 관리 비용 증가를 초래하므로, 실무에서는 트랜잭션을 최대한 짧게 유지하는 것이 권장된다.


5. 실습 다시 보기: 왜 팬텀 리드가 일어났는가?

지난 실습에서 REPEATABLE READ 수준임에도 불구하고 FOR UPDATE를 사용했을 때 새로운 레코드가 보였던(팬텀 리드) 이유는 InnoDB의 내부 처리 방식 차이에 있다.

  1. 일반 SELECT (Consistent Read): 트랜잭션 시작 시점의 Undo 로그 스냅샷을 읽는다. 따라서 다른 세션이 데이터를 추가해도 보이지 않는다.
  2. LOCKING READ (SELECT ... FOR UPDATE): 이 쿼리는 단순히 데이터를 읽는 것이 아니라 수정하기 위해 락을 거는 작업이다. 따라서 스냅샷이 아닌 현재 시점의 실제 디스크 데이터를 직접 조회한다. 이 과정에서 다른 트랜잭션이 추가하고 커밋한 최신 레코드가 조회 범위에 포함되면서 팬텀 리드 현상이 나타나는 것이다.
⚠️ SELECT ... FOR UPDATE는 단순 읽기가 아닌 락을 위한 작업이므로, REPEATABLE READ의 스냅샷을 참조하는게 아니라, 가장 최신 데이터(=실제 디스크 데이터)를 직접 조회한다


6. 요약

데이터베이스의 내부 동작을 로그 관점에서 정리하면 다음과 같다.

  • Redo 로그는 성능과 복구를 위한 '포스트잇'이다. 디스크 쓰기 속도를 극복하고 시스템 장애 시 데이터를 되살린다.
  • Undo 로그는 정합성과 격리를 위한 '백업본'이다. 작업을 되돌리고(Rollback), 격리 수준에 따라 다른 트랜잭션에 과거 데이터를 보여준다.
  • 격리 수준은 이 로그들의 활용도 차이다. Read Committed는 조상(백업본)을 찾고, Repeatable Read는 처음 본 조상을 끝까지 기억하며, Serializable은 아예 접근을 막는다.
  • MVCC 덕분에 읽기 작업은 쓰기 작업을 방해하지 않는다. 다만, 지나치게 긴 트랜잭션은 Undo 로그를 쌓이게 하여 성능을 저하시키므로 주의가 필요하다.

 

'Database > MySQL' 카테고리의 다른 글

[Lock-6][Optimization] 데이터 정합성을 보장하는 락(Lock)의 종류와 전략  (0) 2025.12.25
[Lock-5][Optimization]트랜잭션 실습을 통한 동시성 문제 인식  (0) 2025.12.25
[Lock-3][Optimization] Lock: 격리성 수준(Isolation Level) 심층 분석 및 실습  (0) 2025.12.25
[Lock-2][Optimization] 다중 트랜잭션 환경과 정합성 문제  (0) 2025.12.24
[Lock-1][Optimization] 트랜잭션의 정의와 ACID 원칙  (0) 2025.12.24
'Database/MySQL' 카테고리의 다른 글
  • [Lock-6][Optimization] 데이터 정합성을 보장하는 락(Lock)의 종류와 전략
  • [Lock-5][Optimization]트랜잭션 실습을 통한 동시성 문제 인식
  • [Lock-3][Optimization] Lock: 격리성 수준(Isolation Level) 심층 분석 및 실습
  • [Lock-2][Optimization] 다중 트랜잭션 환경과 정합성 문제
h6bro
h6bro
백엔드 개발자의 기술 블로그
  • h6bro
    Jun's Tech Blog
    h6bro
  • 전체
    오늘
    어제
    • 분류 전체보기 (250) N
      • Java (18)
        • Core (9)
        • Design Pattern (9)
      • Spring (80)
        • Core (24)
        • MVC (6)
        • DB (10)
        • JPA (26)
        • Monitoring (3)
        • Security (11)
        • WebSocket (0)
      • Database (33)
        • Redis (15)
        • MySQL (18)
      • MSA (25) N
        • MSA 기본 (11)
        • MSA 아키텍처 (14) N
      • Kafka (30)
        • Core (18)
        • Connect (12)
      • ElasticSearch (11)
        • Search (11)
        • Logging (0)
      • Test (4)
        • k6 (4)
      • Docker (9)
      • CI&CD (10)
        • GitHub Actions (6)
        • ArgoCD (4)
      • Kubernetes (18)
        • Core (12)
        • Ops (6)
      • Cloud Engineering (4)
        • AWS Infrastructure (3)
        • AWS EKS (1)
        • Terraform (0)
      • Project (8)
        • LinkFolio (1)
        • Secondhand Market (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • Cloud Engineering 포스팅 정리
  • 인기 글

  • 태그

    ㅈ
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
h6bro
[Lock-4][Optimization] Redo/Undo 로그와 MVCC 원리
상단으로

티스토리툴바