ACID는 DB 트랜잭션이 보장해야 할 네 가지 성질이다. 트랜잭션은 "계좌 이체의 출금 + 입금"처럼 함께 성공하거나 함께 실패해야 하는 논리적 작업 단위다.
- Atomicity(원자성): 트랜잭션 안의 작업은 전부 반영되거나 전혀 반영되지 않는다. "출금은 됐는데 입금은 안 됨"이 남지 않는다
- Consistency(일관성): 트랜잭션 전후로 DB가 모든 제약 조건을 만족하는 유효한 상태를 유지한다(데이터 무결성)
- Isolation(격리성): 동시에 도는 트랜잭션들이 서로의 중간 상태를 보지 않는다. 혼자 실행되는 것처럼 보여야 한다
- Durability(지속성): 커밋된 결과는 정전이 나도 남는다. 보통 WAL(Write-Ahead Log)에 먼저 기록해 보장한다
격리 수준(isolation level)
완벽한 격리는 비싸서, DB는 단계를 나눠 고르게 한다.
| 수준 | 막는 것 |
|---|---|
| Read Uncommitted | 거의 없음 |
| Read Committed | 커밋 안 된 값 읽기(dirty read) |
| Repeatable Read | + 같은 행을 다시 읽을 때 값이 바뀜(non-repeatable read) |
| Serializable | + 새 행이 끼어드는 팬텀(phantom read) 등 모든 이상 |
격리를 강하게 할수록 안전하지만 동시성은 떨어진다. PostgreSQL·Oracle의 기본은 Read Committed, MySQL InnoDB의 기본은 Repeatable Read다.
무결성과의 관계
무결성이 지키려는 상태라면 ACID는 그 상태를 지키는 방법이다. C가 제약 유지를 직접 맡고, A·I·D는 동시성과 장애 상황에서도 그 일관성이 깨지지 않게 받친다. 스프링에서 트랜잭션 경계를 긋는 방법은 @Transactional을 본다.
분산 환경에서는
서로 다른 저장소를 한 트랜잭션으로 묶을 수 없으면 ACID 대신 최종 일관성(BASE: Basically Available, Soft state, Eventual consistency)을 받아들이고, 트랜잭셔널 아웃박스 패턴 같은 패턴으로 틈을 메운다.