
여러 트랜잭션이 동시에 실행될 때, 각 트랜잭션이 다른 트랜잭션의 작업에 영향을 받지 않고 독립적으로 실행되는 것처럼 보이게 하는 성질이다. 즉, 진행 중인 트랜잭션이 다른 트랜잭션의 중간 변경 내용을 볼 수 있는지 여부를 제어한다.
고립성이 제대로 지켜지지 않으면 데이터의 일관성이 깨지는 여러 문제들이 발생할 수 있다.
| 고립 수준 | 설명 | 더티 리드 | 반복 불가능한 읽기 | 팬텀 리드 |
|---|---|---|---|---|
| Read Uncommitted | 기장 낮은 수준. 다른 트랜잭션이 커밋하지 않은 변경 내용도 볼 수 있다. | 발생 | 발생 | 발생 |
| Read Committed | 커밋된 변경 내용만 읽을 수 있다. 대부분의 데이터베이스에서 기본값으로 사용된다. | 방지 | 발생 | 발생 |
| Repeatable Read | 트랜잭션이 시작된 이후 다른 트랜잭션에 의해 수정된 내용은 보이지 않아, 반복해서 읽어도 항상 같은 결과를 얻는다. | 방지 | 방지 | 발생 |
| Serializable | 가장 높은 수준. 트랜잭션들을 마치 순서대로 하나씩 실행하는 것처럼 동작하도록 하여 동시성 문제를 완벽히 방지한다. | 방지 | 방지 | 방지 |
각 DBMS는 이러한 구립 수준을 잠금(Locking)을 이용한 비관적 동시성 제어 또는 버전 관리를 이용한 낙관적 동시성 제어 등의 방식으로 다르게 구현할 수 있다.
트랜잭션 간 충돌이 자주 발생할 것이라고 가정하는 '비관적인' 접근법이다. 따라서 데이터 무결성을 지키기 위해, 한 트랜잭션이 데이터에 접근하는 순간부터 잠금(Lock)을 걸어 다른 트랜잭션의 접근을 막는다.
작동 방식:
장점:
단점:
주요 사용 사례: 충돌 발생 시 손실이 큰 금융 거래, 좌석 예약, 재고 관리 등 데이터 정합성이 매우 중요한 시스템에 적합하다.
트랜잭션 간 충돌이 거의 발생하지 않을 것이라고 가정하는 '낙관적인' 접근법이다. 따라서 일단 잠금 없이 모든 트랜잭션의 접근을 허용하고, 트랜잭션이 작업을 마친 후 최종적으로 커밋하는 시점에 충돌이 있었는지 검사한다.
각 DBMS가 특정 고립 수준을 어떻게 구현했는지를 이해하고, 내 서비스의 요구사항과 맞는지를 판단하는 것이 중요하다. ANSI SQL 표준은 각 고립 수준이 '최소한' 보장해야 하는 상항을 정의할 뿐, 실제 DBMS들은 그보다 더 높은 수준의 고립성을 제공하는 경우가 많다.
DBMS마다, 심지어 같은 DBMS의 버전이 스토리지 엔진에 따라서도 고립 수준의 동작 방식이 다르다
REPEATABLE READ이며, MVCC(Multi-Version Concurrency Control) 덕분에 팬텀 리드까지 방지된다. 이는 데이터 일관성을 매우 중요하게 생각하는 설계 철학을 보여준다.READ COMMITTED이다. 하지만 REPEATABLE READ 수준으로 올리면 스냅샷 방식으로 동작하여 팬텀 리드를 방지한다. 이는 성능을 우선시하되, 필요시 높은 수준의 일관성을 제공하는 유연한 접근이다.READ COMMITTED조차 MVCC 기반으로 동작하여, 다른 DBMS라면 REPEATABLE READ 수준에서나 막을 수 있는 반복 불가능한 읽기(Non-repeatable Read) 현상가지 방지해준다.DBMS를 결정할 때 고립성의 구현 방식을 기준으로 성능이나 비요의 트레이드 오프를 따져 기준을 마련하려한다.
어떤 구현 방식을 선택하느냐에 따라 특정 작업(Workload)환경에서의 성능, 개발의 복잡성, 심지어 하드웨어 비용까지 직접적인 영향을 받기 때문이다.
고립성 구현 방식의 트레이드 오프는 두 가지 방식의 차이에서 발생한다.
잠금(Locking) 기반 제어 (비관적): 한 트랜잭션이 데이터에 접근할 때 잠금을 걸어 다른 트랜잭션의 접근을 막는 방식
버전 관리(MVCC) 기반 제어 (낙관적): 데이터를 수정할 때마다 새로운 버전을 만들어 각 트랜잭션이 특정 시점의 데이터 스냅샷을 보도록 하는 방식이다.
쓰기 충돌이 잦은 워크로드 (High Contention)
시나리오: 실시간 예매, 선착순 이벤트, 재고 관리 시스템처럼 여러 사용자가 동시에 같은 데이터를 수정하려는 경합이 심한 경우.
잠금(Locking) 기반이 유리할 수 있는 이유:
예측 가능한 비용: 충돌이 예상되므로 미리 잠금을 걸어 순서를 제어하는 것이 효율적이다. 다른 트랜잭션은 일단 대기하므로, 롤백하고 처음부터 다시 시도하는 낭비가 없다.
개발 비용 감소: 충돌 시 재시도 로직을 애플리케이션에 복잡하게 구현할 필요가 줄어든다.
MVCC 기반의 비용:
읽기 위주의 워크로드 (Read-Heavy)
시나리오: 블로그, 뉴스 사이트, 쇼핑몰의 상품 조회처럼 쓰기 작업보다 읽기 작업이 압도적으로 많은 경우.
MVCC 기반이 압도적으로 유리한 이유:
잠금(Locking) 기반의 비용:
SERIALIZABLE이나 MySQL의 REPEATABLE READ처럼 강력한 고립 수준을 제공하는 DBMS가 필요하다.READ COMMITTED를 기본으로 하여 성능을 확보하는 PostgreSQL이나 Oracle 같은 DBMS가 더 유리할 수 있다.A 서비스에는 B라는 고립 수준이 필요하니 C라는 DBMS를 써야 한다는 공식은 없다. 대신, "내 서비스는 팬텀 리드를 막아야 하는데, 테스트해보니 MySQL의 REPEATABLE READ와 PostgreSQL의 SERIALIZABLE이 그 동작을 보장해주는구나와"와 같이 실제 동작을 기반으로 판단하는 것이 좋은 접근법이다.
| 기준 | Locking 기반 고려 (전통적 RDBMS) | MVCC 기반 고려 (PostgreSQL, MySQL InnoDB 등) |
|---|---|---|
| 주요 워크로드 | 쓰기 경합이 매우 심하고 예측 가능성이 중요할 때 | 읽기 작업이 대부분이며 높은 동시성이 중요할 때 |
| 성능 | 읽기-쓰기 경합 시 성능 저하 가능성 | 읽기 위주 환경에서 최고의 성능 |
| 개발/운영 비용 | 교착상태(Deadlock) 해결 등 잠금 관리에 대한 운영 비용 | 잦은 충돌 시 애플리케이션 재시도 로직 구현에 대한 개발 비용. |