개발자 팁SQL 팁 › 트랜잭션 격리 수준을 언제 올려야 하는가 — 실제로 겪는 이상 현상

트랜잭션 격리 수준을 언제 올려야 하는가 — 실제로 겪는 이상 현상

2026-08-28 · SQL 팁
한 줄 요약

격리 수준의 이론적 정의보다 어떤 증상이 나올 때 무엇을 바꿔야 하는지를 정리한다.

정의보다 증상으로

격리 수준은 표로 외우기 쉽지만, 실무에서 필요한 것은 어떤 증상이 나올 때 무엇을 바꾸는가이다.

| 증상 | 이름 | 막는 수준 |

|---|---|---|

| 커밋 안 된 값을 읽음 | 더티 리드 | READ COMMITTED 이상 |

| 같은 행을 두 번 읽었는데 값이 다름 | 논리피터블 리드 | REPEATABLE READ 이상 |

| 같은 조건으로 두 번 조회했는데 행이 늘어남 | 팬텀 리드 | SERIALIZABLE (구현에 따라 다름) |

기본값 확인부터

DB마다 기본 격리 수준이 다르다.

같은 코드가 DB에 따라 다르게 동작할 수 있는 지점이다. 이식할 때 먼저 확인한다.

흔한 실제 문제 — 읽고 나서 쓰기

격리 수준으로 자주 착각하는 상황이 있다.

```

  1. 재고를 읽는다 (10개)
  2. 애플리케이션에서 계산한다 (10 - 1 = 9)
  3. 9로 업데이트한다

```

두 요청이 동시에 오면 둘 다 10을 읽고 둘 다 9를 쓴다. 2개가 팔렸는데 재고는 1개만 줄어든다.

이 문제는 격리 수준을 올려도 완전히 해결되지 않는다. READ COMMITTED에서는 그대로 발생하고, REPEATABLE READ에서도 구현에 따라 다르다.

해결 방식:

1. 조건부 UPDATE (원자적 연산)

```sql

UPDATE items SET stock = stock - 1

WHERE id = ? AND stock >= 1;

```

영향받은 행이 0이면 재고가 없던 것이다. 읽기-계산-쓰기가 한 문장으로 합쳐져 경합이 사라진다.

2. 명시적 락

```sql

SELECT stock FROM items WHERE id = ? FOR UPDATE;

```

다른 트랜잭션이 대기하게 된다. 처리량은 떨어지지만 복잡한 계산이 필요할 때 쓴다.

3. 낙관적 잠금

버전 컬럼을 두고 업데이트 시 확인한다.

```sql

UPDATE items SET stock = ?, version = version + 1

WHERE id = ? AND version = ?;

```

충돌 시 재시도 로직이 필요하다.

격리 수준을 올릴 때의 대가

SERIALIZABLE로 올리면 이상 현상은 사라지지만:

특히 두 번째를 준비하지 않고 격리 수준만 올리면, 간헐적 실패가 늘어난 것처럼 보인다.

트랜잭션 범위

격리 수준보다 먼저 볼 것이 트랜잭션의 길이다.

```

나쁨: 외부 호출이 트랜잭션 안에 있음

BEGIN

UPDATE ...

외부 API 호출 (수 초) ← 이 동안 락 유지

UPDATE ...

COMMIT

```

트랜잭션이 길수록 락 유지 시간이 길고 경합이 커진다. 외부 호출·파일 처리·긴 계산은 트랜잭션 밖으로 뺀다.

판단 순서

  1. 문제가 실제로 관찰되는가 (로그·데이터 불일치)
  2. 그 문제가 격리 수준으로 해결되는 종류인가
  3. 원자적 연산으로 바꿀 수 있는가 → 대개 이쪽이 낫다
  4. 안 되면 락 또는 격리 수준 상향 + 재시도

3번을 먼저 검토하지 않고 격리 수준부터 올리는 경우가 흔한데, 조건부 UPDATE 한 줄로 끝나는 문제가 많다.

최종 수정 2026-08-28

자주 묻는 질문

기본 격리 수준이 무엇인가요?

DB마다 다릅니다. PostgreSQL은 READ COMMITTED, MySQL(InnoDB)은 REPEATABLE READ가 기본입니다.

격리 수준을 올리면 항상 안전한가요?

이상 현상은 줄지만 락 경합과 직렬화 실패가 늘어 처리량이 떨어집니다.

재고 차감 같은 것은 어떻게 처리하나요?

격리 수준만으로 해결하기보다 조건부 UPDATE나 명시적 락을 쓰는 방식이 흔합니다.

DB Linker로 지금 시작하기

AI 채팅으로 데이터베이스를 조회·관리하는 로컬 전용 개발자 도구. 자체 서버 없이 이용자의 기기에서만 동작합니다.

App Store에서 받기 →

안내

이 글은 일반적인 데이터베이스 관리 원칙과 개발 관행을 다루는 콘텐츠이며, 특정 프로젝트·프로덕션 환경에 대한 전문적 조언을 대체하지 않습니다. 구체적 버전·수치가 언급되더라도 실제 사용 중인 도구·버전에서 반드시 재확인하시기 바랍니다.

글 중 일부는 AI 도구의 도움을 받아 초안을 작성한 뒤 발행됩니다. 내용 중 사실과 다르거나 수정이 필요한 부분을 발견하시면 GitHub Issues로 알려주세요.