ballqs 님의 블로그
[DB] 격리수준(Isolation) 본문
격리 수준이란?
다른 트랜잭션과 어떻게 상호작용하는지 결정하는 정책
격리 수준 단계
READ_UNCOMMITTED (읽기 미확정)
가장 낮은 격리 상태이며 트랜잭션이 아직 커밋되지 않은 데이터를 다른 트랜잭션에서 읽을 수 있다.
더티 리드(Dirty Read) 현상이 발생할 수 있습니다. 이는 한 트랜잭션이 아직 커밋되지 않은 데이터를 읽었을 때, 그 트랜잭션이 롤백되면 잘못된 데이터를 읽은 것이 된다.
트랜잭션 1
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET autocommit = 0;
# TRANSACTION 시작
START TRANSACTION;
# 조회
SELECT * from course;
# UPDATE
UPDATE course SET name="java123" WHERE course_id=1;
트랜잭션 2
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET autocommit = 0;
# TRANSACTION 시작
START TRANSACTION;
# UPDATE하고 나서 조회
SELECT * from course;
트랜잭션 2의 SELECT 결과
※Dirty Read(더티 리드)
Dirty Read 는 다른 트랜잭션에서 변경이 되고 있는 데이터(커밋되지 않은 데이터) 를 실시간으로 읽을 수 있는 상황을 뜻한다.
Dirty Read 가 발생한 시점의 데이터를 기반으로 수강신청 같은 중요한 작업이 이루어진다면 문제가 될 수 있다. 트랜잭션 A 에서 rollback 이 발생한다면, 트랜잭션 B 에서 자바 수업으로 수강신청을 했지만, 결과적으로 react 수업에 수강신청이 되어버립니다.
READ_COMMITED (읽기 확정)
READ_UNCOMMITTED 보다 한단계 높은 격리 수준이며 커밋된 데이터만 읽을 수 있다. 아직 커밋되지 않은 데이터는 읽지 못하므로 Dirty Read가 발생하지 않는다.
Non-repeatable Read 현상이 발생할 수가 있다. 동일한 데이터를 읽을 때 중간에 다른 트랜잭션에서 해당 데이터가 변경되는 경우가 있다.
트랜잭션1
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET autocommit = 0;
# TRANSACTION 시작
START TRANSACTION;
# 조회
SELECT * from course;
# UPDATE
UPDATE course SET name="java123" WHERE course_id=1;
트랜잭션2
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET autocommit = 0;
# TRANSACTION 시작
START TRANSACTION;
# UPDATE하고 나서 조회
SELECT * from course;
트랜잭션 1 Commit 하기 전
트랜잭션 1 Commit 후
※Non-repeatable Read
전 처럼 트랜잭션 A 에서 롤백이 발생한 경우, 트랜잭션 B 가 영향을 받지 않는다.
하지만 rollback 이 아니라 트랜잭션 A 에서 데이터 변경이 성공적으로 커밋된다면, 트랜잭션 B 는 여전히 변경된 값을 읽어 처리하기 때문에 예상치 못한 동작이 발생할 수 있다.
같은 트랜잭션 내에서 동일한 데이터를 여러번 읽을 때 그 값이 달라져 데이터 일관성을 보장할 수 없는 문제가 바로 Non-repeatable Read 문제이다.
REPEATABLE_READ (반복 가능 읽기)
트랜잭션 내에서 동일한 데이터를 여러 번 읽을 때, 항상 같은 결과를 반환하도록 보장합니다. 즉, 트랜잭션이 시작된 이후 다른 트랜잭션에서 해당 데이터를 수정할 수 없습니다.
Phantom Read(팬텀 리드) 현상이 발생합니다. 동일한 조건으로 조회할 때, 중간에 다른 트랜잭션이 새로운 데이터를 삽입하면, 조회 결과가 달라질 수 있다.
트랜잭션 1
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET autocommit = 0;
# TRANSACTION 시작
START TRANSACTION;
# 조회
SELECT * from course;
# UPDATE
UPDATE course SET name="java123" WHERE course_id=1;
COMMIT;
트랜잭션 2
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET autocommit = 0;
# TRANSACTION 시작
START TRANSACTION;
# UPDATE하고 나서 조회
SELECT * FROM course;
트랜잭션 1 Commit 전
트랜잭션 1 Commit 후
※Phantom Read
아쉽게도 mysql에서는 Phantom Read 문제를 확인할 수 없다. 내부적으로 갭락(GapLock) 기술을 통해 Phantom Read를 방지하고 있다.
REPEATABLE READ 격리 수준에서는 한번 조회한 데이터는 반복해서 조회했을 때도 같은 데이터가 나와야하지만, 조회시 조회했던 데이터의 집합이 달라지는 경우를 Phantom Read 문제라고 한다.
SERIALIZABLE
가장 높은 수준의 트랜잭션 격리로, 모든 트랜잭션을 순차적으로 실행하는 것처럼 처리한다. 이는 실제로 트랜잭션을 동시에 실행하지만, 그 효과는 순차적으로 실행된 것과 같다.
데이터의 일관성은 보장할 수 있지만 대기 시간이 많이 발생하기에 성능 문제가 심각하게 발생한다.
격리 수준 요약
격리 수준 | 더티 리드 (Dirty Read) | Non-repeatable Read | Phantom Read |
Read Uncommitted | 발생 | 발생 | 발생 |
Read Committed | 발생하지 않음 | 발생 | 발생 |
Repeatable Read | 발생하지 않음 | 발생하지 않음 | 발생 |
Serializable | 발생하지 않음 | 발생하지 않음 | 발생하지 않음 |
'코딩 공부 > DB' 카테고리의 다른 글
[DB] 키의 종류 (0) | 2024.09.16 |
---|---|
[SQL] 입양 시각 구하기(2) 문제 (0) | 2024.08.12 |