본문 바로가기
C.W.K.
Stream
Lesson 08 of 10 · published

ACID를 평범한 말로

~14 min · foundations, transactions

Level 0스키마 새싹
0 XP0/86 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

송금 도중 전원이 꺼진다면

ATM에서 당좌 계좌의 $500를 저축 계좌로 옮긴다고 해보자. 먼저 한 계좌에서 돈을 뺐는데 바로 그 순간 전원이 나가면 어떻게 될까? ACID가 없다면 $500가 한쪽에서는 사라지고 다른 쪽에는 들어오지 않은 채 작업이 끝날 수 있어. ACID는 이런 반쪽짜리 변경을 허용하지 않겠다는 네 글자의 약속이야.

Atomicity, 원자성: 전부 아니면 전무

트랜잭션은 더 쪼갤 수 없는 한 작업 단위야. 어느 단계에서든 실패하면 앞선 단계까지 모두 시작 전 상태로 되돌려. ATM 송금에서는 출금과 입금을 BEGIN ... COMMIT 안에 함께 넣기만 하면 나머지 원자성은 PostgreSQL이 맡아.

Consistency, 일관성: 규칙은 늘 성립해야 해

NOT NULL, CHECK, 외래 키, 고유 색인 같은 제약은 변경이 확정될 때마다 검사돼. 트랜잭션은 정의된 규칙을 어긴 상태를 남길 수 없어. “잔액 ≥ 0”이라는 CHECK가 있다면 어떤 경로로 값을 바꾸더라도 그 선을 넘지 못해.

Isolation, 격리성: 동시에 움직여도 서로 망치지 않아

여러 트랜잭션이 함께 실행되더라도 결과는 정해진 순서로 실행한 것처럼 일관되어야 해. PostgreSQL은 MVCC, 즉 다중 버전 동시성 제어로 이를 구현해. 읽는 작업과 쓰는 작업이 불필요하게 서로를 막지 않으면서 각 트랜잭션은 자기에게 일관된 스냅샷을 봐.

Durability, 지속성: 확정했다면 살아남아야 해

COMMIT이 성공하면 변경은 디스크에 남아야 해. PostgreSQL은 성공 응답을 보내기 전에 WAL, 즉 미리 쓰기 로그를 먼저 저장해. 1ms 뒤 서버가 멈춰도 복구 과정에서 WAL을 다시 읽어 확정된 데이터를 되살려.

Code

원자적인 계좌 이체·sql
BEGIN;
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;
COMMIT;
-- 둘 다 바뀌거나, 아무것도 안 바뀜. 부분 상태 없음.
제약으로 일관성 지키기·sql
ALTER TABLE accounts
ADD CONSTRAINT positive_balance CHECK (balance >= 0);

-- 이제 overdraw 되는 이체는 COMMIT 에서 거절:
BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;  -- balance = -500
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
COMMIT;
-- ERROR: new row violates check constraint "positive_balance"
격리된 동시 읽기·sql
-- Session A                          | -- Session B
BEGIN;                                | BEGIN;
SELECT SUM(balance) FROM accounts;    | UPDATE accounts SET balance = balance + 100
                                      |   WHERE id = 7;
                                      | COMMIT;
SELECT SUM(balance) FROM accounts;    |
-- A 는 같은 합계 두 번 봄, B 가 중간에 commit 했어도.
-- MVCC 가 각 트랜잭션에 일관된 스냅샷 줘.
COMMIT;

External links

Exercise

같은 데이터베이스에 psql 연결을 두 개 열어. 세션 A에서 BEGIN 뒤 한 행을 UPDATE하고, 세션 B에서 같은 행을 SELECT한 다음 UPDATE해봐. 무엇이 기다리고 무엇은 바로 실행되는지 관찰해. 이어서 A에서 COMMIT했을 때와 ROLLBACK했을 때 결과가 어떻게 달라지는지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.