ACID — 이체 한 건으로 네 글자 전부
계좌 이체 하나로 원자성(크래시 롤백), 일관성(제약 거부), 격리성(더티 리드 차단), 지속성(WAL 재생)을 각각 시나리오로 실행한다.
트랜잭션: 대기
단계 목록 · 키보드 ←/→ 이동, Space 재생
원자성=전부 아니면 전무, 일관성=규칙은 언제나 참, 격리성=동시지만 차례처럼, 지속성=커밋은 영원히 — 네 글자는 각각 다른 사고를 막고, 다른 장치(롤백·제약·잠금/MVCC·WAL)로 구현된다.
왜 헷갈리는가
'일관성'이 최대 함정이다 — CAP 정리의 일관성(복제본이 같은 값)과 ACID의 일관성(제약·불변식 유지)은 같은 단어의 다른 개념이다. 또 격리성은 on/off가 아니라 수준(Read Committed → Serializable)의 스펙트럼인데, 기본값이 DB마다 달라 사고가 난다.
애니메이션이 보여주는 것
네 장면이 각각 하나의 사고를 막는다. 원자성: 출금까지 하고 죽어도 재시작 시 롤백 — 5만원이 증발한 중간 상태는 존재한 적이 없게 된다. 일관성: '잔액 ≥ 0' 제약을 어기는 트랜잭션은 커밋 자체가 거부된다. 격리성: 이체 도중의 총액 15만원(돈이 증발한 순간)을 감사 질의가 보느냐 — 격리 수준이 그 장면을 감춘다. 지속성: 커밋의 실체는 WAL 디스크 기록이라 정전 후에도 로그 재생으로 복원된다.
격리 수준 — 스펙트럼의 감각
격리성만은 수준을 알아야 실무가 된다.
- Read Uncommitted: 더티 리드 허용(애니메이션의 15만원 장면) — 실무에서 거의 안 쓴다.
- Read Committed(PostgreSQL 기본): 커밋된 것만 읽음. 단, 같은 트랜잭션에서 두 번 읽으면 값이 바뀔 수 있다(비반복 읽기).
- Repeatable Read(MySQL InnoDB 기본): 트랜잭션 시작 시점의 스냅숏 고정 — MVCC가 잠금 없이 이를 만든다.
- Serializable: 완전한 '차례처럼' — 가장 안전하고 가장 느리며, 직렬화 실패 재시도 로직이 필요하다.
- 실무 사고의 전형: 기본 격리 수준만 믿고 '재고 확인 후 차감'을 짜면 두 트랜잭션이 같은 재고를 본다 — SELECT FOR UPDATE나 원자적 UPDATE로 풀어야 한다.
네 글자의 구현 장치
원자성은 언두 로그/롤백이, 일관성은 제약 검사(+애플리케이션 불변식)가, 격리성은 잠금과 MVCC가, 지속성은 WAL(fsync)이 맡는다. 'ACID를 지원한다'는 말은 이 네 장치의 품질 문제다 — 분산 DB에서 이 장치들이 얼마나 비싸지는가가 NewSQL·사가 패턴 논의의 출발점이다.
기억할 것
- A=전부/전무(롤백), C=규칙 유지(제약), I=차례처럼(잠금/MVCC), D=영원히(WAL).
- CAP의 C와 ACID의 C는 다른 개념 — 같은 단어에 속지 말 것.
- 격리성은 스펙트럼 — DB 기본값(PG: RC, MySQL: RR)부터 확인하라.
- 커밋의 실체는 WAL 디스크 기록 — '커밋됐다'는 말은 fsync의 약속이다.