본문 바로가기
CS

CS 스터디 (DB) 24 - 트랜잭션 격리 수준에 대해 설명해주세요.

by gentle-tiger 2025. 5. 23.

트랜잭션 격리 수준 

- 트랜잭션은 ACID라는 네 가지 특징이 있으며, 그중 격리성(Isolation)은 트랜잭션 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 것을 의미합니다. 

- 격리 수준이 높아질수록 트랜잭션 간 간섭은 줄어들지만, 동시처리 성능은 낮아지고 성능 비용이 증가합니다.

 

트랜잭션 격리 수준 레벨 

Read Uncommitted → Serizlizable 순으로 동시성은 낮아지고, 격리성은 높아집니다.

- MySQL은 REPEATABLE_READ, Oracle은 READ_COMMITTED가 기본 격리 수준입니다. 

격리 레벨 정의 Dirty Read Non-Repeatable Read Phantom Read
Read Uncommitted 커밋되지 않은 데이터도 읽을 수 있는 가장 낮은 격리 수준. O O O
Read Committed
커밋된 데이터만 읽을 수 있는 수준. X O O
Repeatable Read
동일한 트랜잭션 내에서 동일한 쿼리를 반복 실행해도 항상 같은 결과를 반환하는 격리 수준. X X O

Serializable
가장 높은 격리 수준으로, 트랜잭션이 순차적으로 실행되는 것처럼 동작. X X X

 

MVCC (다중 버전 동시성 제어)

- MVCC는 변경 전의 레코드를 Undo 공간에 백업하여 트랜잭션 번호를 참고해 먼저 실행된 트랜잭션 데이터만 조회하는 방법입니다.

- 트랜잭션 번호는 트랜잭션 시작시점이 아닌, 최초 데이터 접근 시점에 할당 받습니다. 

- 메모리와 Undo 공간에 여러 버전의 데이터가 존재하고 있어서 다중 버전이라고 합니다.

 

트랜잭션 격리 수준에 따라 발생할 수 있는 문제점

Phantom Read

- 한 트랜잭션 내에서 동일 쿼리를 보냈을 때 조회 결과가 다른 경우 (By Insert, Delete)

- Repeatable Read에서는 발생 가능, Serializable에서만 방지.

- 예) 같은 WHERE 조건으로 조회했는데, 그 사이 누군가 INSERT/DELETE를 해서 행 개수가 바뀌는 상황 

-- 트랜잭션 A
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM orders WHERE amount > 100;
-- 결과: 3건

-- 그 사이, 트랜잭션 B
START TRANSACTION;
INSERT INTO orders (id, amount) VALUES (99, 200);
COMMIT;

-- 트랜잭션 A 다시 조회
SELECT * FROM orders WHERE amount > 100;
-- 결과: 4건 (새로운 행이 생김 = 팬텀)

 

Non-Repeatable Read

- 한 트랜잭션 내에서 동일 쿼리를 두번 이상 조회 했는데, 그 값이 다른 경우 (By Update)

- Read Committed 이상에서 방지되며, Repeatable Read 이상에서 해결

- 예) 같은 SELECT를 두 번 했는데, 그 사이 다른 트랜잭션이 값을 변경해버려 결과가 달라지는 상황

-- 트랜잭션 A
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1;
-- 결과: 1000

-- 그 사이, 트랜잭션 B
START TRANSACTION;
UPDATE accounts SET balance = 800 WHERE id = 1;
COMMIT;

-- 트랜잭션 A 다시 조회
SELECT balance FROM accounts WHERE id = 1;
-- 결과: 800 (값 바뀜)

 

Dirty Read

- 다른 트랜잭션에 의해 수정되었지만 아직 커밋되지 않은 데이터를 읽는 경우 (By Update)

- Read Uncommitted 격리 수준에서만 발생

- 예) 트랜잭션 A가 아직 커밋하지 않은 데이터를, 트랜잭션 B가 읽어버리는 상황. 

-- 트랜잭션 A
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- COMMIT 또는 ROLLBACK 없이 대기

-- 그 사이, 트랜잭션 B
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1;
-- A가 커밋 안 했는데도 변경된 값이 보임
문제 발생 가능한 수준 방지 가능한 수준
Dirty Read Read Uncommitted Read Committed 이상
Non-Repeatable Read Read Committed Repeatable Read 이상
Phantom Read Repeatable Read Serializable

 

 

 

 

결론 

트랜잭션 격리 수준은 ACID 네 가지 속성 중 Isolation을 구현한 것으로, 하나의 트랜잭션에 다른 트랜잭션의 연산이 끼어들지 못하게 만드는 ‘차단 강도’를 의미합니다. Read Uncommitted → Read Committed → Repeatable Read → Serializable 순으로 격리성이 높아지지만, 그만큼 동시성(성능) 손실이 커집니다. 즉, 격리 수준을 높여 무결성을 강화할수록 테이블·레코드 잠금이 길어져 처리량이 떨어질 수 있습니다.

격리 수준이 낮으면 세 가지 대표적인 문제 Dirty Read, Non-Repeatable Read, Phantom Read가 발생합니다. Dirty Read는 아직 커밋되지 않은 데이터를 읽는 현상으로, Read Committed 이상이면 막을 수 있습니다. Non-Repeatable Read는 한 트랜잭션 안에서 같은 행을 두 번 조회했을 때 값이 달라지는 경우로, Repeatable Read 이상이면 차단됩니다. 마지막으로 Phantom Read는 동일 조건으로 행 집합을 재조회할 때 행 수가 달라지는 현상이며, 완전한 차단은 Serializable에서만 가능합니다.