데이터베이스 용어 사전
동시성 제어언두 로그 · purge

undo log

InnoDB가 옛 버전을 재구성하기 위해 남기는 변경 이력. 롤백과 MVCC 읽기에 함께 쓰인다.

MySQL InnoDB가 변경 전 값을 기록해 두는 로그. 두 가지 일을 동시에 한다 — 롤백MVCC 읽기다.

PostgreSQL과 반대 방향의 설계

  • [PostgreSQL] — 새 버전을 테이블(힙)에 쌓는다

    • 테이블이 부푼다 → VACUUM 이 청소
  • [InnoDB] — 테이블에는 최신 버전만 두고,

    • 옛 값은 undo log 에 따로 쌓는다
    • 옛 버전이 필요하면 undo 를 거꾸로 따라가 재구성

각 행에는 숨은 칼럼이 있다.

  • DB_TRX_ID — 이 행을 마지막으로 바꾼 트랜잭션 ID
  • DB_ROLL_PTR — undo log 의 해당 항목을 가리키는 포인터

옛 버전을 어떻게 만들어 내나

  • 현재 행: — balance = 5000, TRX_ID = 300, ROLL_PTR → undo#7

트랜잭션 200 이 이 행을 읽는다

  • "300은 내 시점 이후다" → 이 버전은 못 본다
  • ROLL_PTR 을 따라 undo#7 로 간다 → balance = 10000, TRX_ID = 150
  • "150은 내 시점 이전이다" → 이 버전을 본다

트랜잭션은 read view(자기 시점에 보이는 트랜잭션 ID 집합)로 이 판단을 한다.

두 역할이 한 로그에 겹친다

  • 롤백 — ROLLBACK 시 undo 를 역순으로 적용해 원래 값으로 되돌린다
  • MVCC — 옛 버전이 필요한 읽기에 그 이력을 그대로 재활용한다

하나의 자료구조가 두 목적을 겸하는 것이 InnoDB 설계의 특징이다. (변경 값을 기록해 장애 복구에 쓰는 redo log와는 방향이 반대다.)

긴 트랜잭션이 만드는 문제

-- undo 히스토리 길이 확인
SHOW ENGINE INNODB STATUS\G       -- "History list length" 항목
긴 트랜잭션이 열려 있으면
  → purge 스레드가 undo 를 못 지운다
  → History list length 가 계속 는다
  → 옛 버전을 여러 단계 거슬러 올라가야 해서 조회가 느려진다

PostgreSQL의 bloat와 원인도 처방도 같다 — 트랜잭션을 짧게 유지하는 것이다.

면접 함정

  • "undo log와 redo log는 같은 것" → undo는 변경 전 값(롤백·MVCC), redo는 변경 후 값(장애 복구)이다.
  • "InnoDB는 MVCC라 VACUUM 같은 게 필요 없다" → purge가 같은 일을 한다. 긴 트랜잭션에 막히는 것도 같다.

크기와 위치 확인하기

-- undo 테이블스페이스 크기
SELECT tablespace_name, file_name, file_size/1024/1024 AS mb
  FROM information_schema.files WHERE file_type = 'UNDO LOG';

-- 가장 오래 열린 트랜잭션 — undo 를 붙잡고 있는 범인
SELECT trx_id, trx_started,
       TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS sec, trx_query
  FROM information_schema.innodb_trx ORDER BY trx_started LIMIT 5;

History list length가 왜 중요한가

  • History list length = 아직 purge 되지 않은 undo 항목 수

  • 정상 — 수천 이하

  • 주의 — 수십만 — 긴 트랜잭션을 찾아본다

  • 위험 — 수백만 — 조회가 눈에 띄게 느려지고 디스크가 찬다

값이 크면 옛 버전을 여러 단계 거슬러 올라가야 하므로 읽기 자체가 느려진다. PostgreSQL의 bloat는 공간 문제로 나타나지만, InnoDB의 undo 적체는 조회 지연으로 먼저 나타난다는 차이가 있다.

undo 테이블스페이스는 자동으로 줄지 않았다

-- MySQL 8.0+ 는 자동 truncate 를 지원한다
SHOW VARIABLES LIKE 'innodb_undo_log_truncate';   -- ON 이어야 한다
SHOW VARIABLES LIKE 'innodb_max_undo_log_size';   -- 이 크기를 넘으면 잘라 낸다

이전 버전에서는 한 번 커진 undo 파일이 줄지 않아 디스크가 계속 차는 문제가 있었다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 동시성 제어 — 2PL·MVCC·락·데드락(PostgreSQL·MySQL)