"Atomicity / Consistency / Isolation / Durability — 매 transaction 의 four guarantees." Härder & Reuter (1983) 가 정식화한 properties. 매 RDBMS (Postgres, Oracle, MySQL InnoDB) 의 default 보장이며, 2026 distributed era 에도 매 NewSQL (CockroachDB, Spanner, TiDB, Neon) 가 매 ACID across nodes 를 표방. 매 단일 transaction 이 매 multi-statement 의 all-or-nothing + isolated + persisted 를 보장.
매 핵심
매 4 properties
Atomicity: 매 all statements commit or all rollback. 매 partial state 없음.
Consistency: 매 transaction 종료 시 매 모든 invariant (FK, check, unique) 가 valid.
Isolation: 매 concurrent transactions 가 매 serially executed 처럼 보임. 매 isolation level 로 trade-off.
Durability: 매 commit 후 매 crash / power loss 에도 매 data 가 살아남음 (WAL → fsync).
매 Isolation levels (SQL standard + Postgres)
Read Uncommitted: 매 dirty read 허용 (Postgres 는 사실상 RC 로 mapping).
Read Committed (Postgres default): 매 dirty read X, 매 non-repeatable read O.
Repeatable Read (Postgres = snapshot isolation): 매 phantom read 거의 없음, 매 serialization anomaly O.
Serializable (Postgres = SSI): 매 strictest, 매 overhead 큼.
매 응용
매 financial / inventory 의 multi-row update.
매 idempotent worker — 매 transaction + unique key.
매 saga compensation 의 단위.
💻 패턴
1) Postgres BEGIN/COMMIT
BEGIN;UPDATEaccountsSETbalance=balance-100WHEREid=1;UPDATEaccountsSETbalance=balance+100WHEREid=2;COMMIT;-- 매 atomic + durable
2) SAVEPOINT 로 partial rollback
BEGIN;INSERTINTOorders(id,total)VALUES(1,50);SAVEPOINTbefore_items;INSERTINTOitems(order_id,sku)VALUES(1,'BAD-SKU');-- FK 위반
ROLLBACKTOSAVEPOINTbefore_items;INSERTINTOitems(order_id,sku)VALUES(1,'OK');COMMIT;
3) Isolation level 명시 (Python + asyncpg)
asyncwithconn.transaction(isolation="serializable"):row=awaitconn.fetchrow("SELECT balance FROM accounts WHERE id=$1",1)awaitconn.execute("UPDATE accounts SET balance=$1 WHERE id=$2",row["balance"]-100,1)# 매 SSI — 매 serialization_failure 시 retry 필요
4) Optimistic concurrency (version column)
UPDATEdocSETbody=$1,version=version+1WHEREid=$2ANDversion=$3;-- 매 affected_rows = 0 → conflict, 매 retry / 사용자 alert
5) SELECT FOR UPDATE (pessimistic lock)
BEGIN;SELECT*FROMaccountsWHEREid=1FORUPDATE;-- 매 row lock
UPDATEaccountsSETbalance=balance-100WHEREid=1;COMMIT;
6) Outbox pattern (transaction + async publish)
BEGIN;INSERTINTOorders(id,...)VALUES(...);INSERTINTOoutbox(event_type,payload)VALUES('OrderCreated',$1);COMMIT;-- 매 separate worker 가 outbox 를 읽고 매 broker 로 publish
언제: 매 codegen 의 SQL transaction boundary 검증, 매 isolation level mismatch 점검.
언제 X: 매 eventually-consistent NoSQL (DynamoDB single-region) — 매 BASE 모델로 reasoning.
❌ 안티패턴
App-side "transaction": 매 read-modify-write 가 매 BEGIN/COMMIT 밖. 매 race condition.
Long transaction: 매 minutes 단위 hold → 매 lock contention + bloat.
Wrong isolation: 매 default RC 에서 매 lost update 발생, 매 detect 못 함.
Ignoring serialization failure: 매 SSI 에서 매 retry 안 함 → 매 user-facing error.
Transaction across services: 매 distributed XA 시도 → 매 saga 로 대체.