트랜잭션 격리 수준
- 트랜잭션은 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에서만 가능합니다.
'CS' 카테고리의 다른 글
CS 스터디 (DB) 26 - 클러스터링과 레플리케이션에 대해 설명해주세요. (0) | 2025.05.26 |
---|---|
CS 스터디 (DB) 25 - DB 락에 대해 설명해주세요. (0) | 2025.05.26 |
CS 스터디 (DB) 23 - 트랜잭션의 특성은 무엇인가요? (0) | 2025.05.23 |
CS 스터디 (DB) 22 - 옵티마이저란 무엇인가요? (0) | 2025.05.23 |
CS 스터디 (DB) 20 - 인덱스를 타지 않거나 혹은 기대하는 성능을 못내는 경우는? (0) | 2025.05.23 |