이전 글
https://larcane.tistory.com/46
Repeatable Read
하나의 트랜잭션 내에서 여러 번 조회를 해도 일관된 값을 읽는 것을 보장하는 격리수준
- repeatable read에서는 phantom read가 발생할 수 있다.
- MySQL에서는 undo log를 통해 repeatable read를 보장
undo log에서 자신의 TID 이전의 값만 조회하도록 함
- Lock을 사용하지 않는 조회의 경우에는 항상 repeatable read함을 보장
Phantom Read
다른 트랜잭션에 의해 추가(INSERT)된 레코드가 하나의 트랜잭션 내에서 보였다 안 보였다 하는 현상
MVCC 환경에서는 Repeatable read 수준에서 Lock을 사용하지 않는 조회의 경우 Phantom read 현상이 발생하지 않음
- 다른 트랜잭션에서 값을 추가(Insert)하든, 수정(Update)하든 undo log에서 자신의 trx-id보다 낮은 값을 읽으면 되기 때문
Phantom read가 발생하는 경우는 Lock을 사용하는 SELECT를 사용하는 경우 발생할 수 있다.
- SELECT … for UPDATE와 같이 LOCK을 사용하는 SELECT의 경우 값을 항상 테이블에서 가져온다.

- 사용자 B의 첫 번째 SELECT에서 id = 50에 대해 레코드 락을 걸어놓았지만, 사용자 A가 추가한 값은 id = 51이므로 락이 걸려 있지 않아 값이 추가가 된다.
하지만 MySQL에서는 넥스트 키 락을 통해 위와 같은 Phantom read 현상을 방지할 수 있다.
- 사용자 B의 첫 번째 SELECT에서 id = 50에 대한 레코드 락 뿐만 아니라 id > 50에 대한 갭 락이 적용되기 때문

MySQL의 Repeatable read에서는 Lock을 사용하는 Select, Update, Delete 등 Lock이 필요한 상황에 넥스트 키 락과 MVCC(undo log)를 사용해 Phantom read를 방지
Read Committed
다른 트랜잭션에서 commit한 값만 읽을 수 있도록 보장하는 격리수준
- read committed에서는 non-repeatable read와 phantom read 현상이 발생할 수 있다.
Repeatable read와 다르게, Undo log에서 trx-id와 상관없이 값을 읽도록 한다.
- 또한 transaction이 commit되면 바로 undo log에서 값을 지워 commit된 값을 테이블에서 바로 읽을 수 있도록 함

Non-Repeatable Read
Read Committed 격리 수준에서는 undo log를 commit 시 바로 삭제하기 때문에 non-repeatable read 현상이 발생할 수 있다.

- 사용자 B가 SELECT를 통해 값을 조회
- 사용자 A가 UPDATE를 통해 값을 수정 후 COMMIT
- undo log에 저장되었다가 COMMIT된 순간 바로 삭제된다.
- 사용자 B가 SELECT를 통해 값을 다시 조회하면 새로운 값이 조회된다.
Phantom Read
Read Committed 격리 수준에서는 Lock을 사용하는 SELECT, UPDATE, DELETE 등을 수행할 때, 레코드 락만을 사용한다.
- 갭 락을 사용하지 않기 때문에 Phantom read가 발생할 수 있다.

Read UnCommitted
다른 트랜잭션에서 commit하지 않은 데이터까지 볼 수 있는 격리 수준
- MVCC(undo log)를 사용하지 않고, 트랜잭션에서 값이 변경되면 바로 테이블에 반영한다.
- dirty read 현상이 발생한다.
Dirty read
특정 값이 읽을 때마다 변경되는 현상
- 다른 Transaction에서 값을 변경하고 롤백이 되는 경우 발생 할 수 있다.

Serializable
MySQL에서는 기본적으로 Repeatable Read 격리 수준과 비슷
- 차이점 : SELECT 쿼리가 전부 SELECT ... FOR SHARE로 자동으로 변경
정리
트랜잭션 격리 수준과 락
트랜잭션 격리 수준 : 서로 다른 트랜잭션 간의 작업 내용의 간섭 범위를 나타내는 것
락 : 동시성을 제어하기 위한 하나의 방법
락은 특정 트랜잭션 격리 수준을 달성하기 위한 방법 중 한 가지로 사용되는 것
- 서로 다른 트랜잭션 간의 간섭 범위를 줄이려면 동시성을 어느정도 제어해야 한다는 것과 같은 의미
트랜잭션 격리 수준 비교
| Serializable | Repeatable Read | Read Committed | Read UnCommitted | |
| Undo-log 사용 여부 | O | O | O | X |
| Undo-log history 사용 여부 | O | O | X | X |
| 갭락 사용 여부 | O | O | X | X |
| SELECT → SELECT .. FOR SHARING 변경 여부 | O | X | X | X |
- Undo log : Read Committed 격리 수준 달성
- Undo log + Undo log history : LOCK을 사용하지 않는 SELECT에 대해서 Repeatable Read 격리 수준 달성
- Undo log + Undo log history + 갭락 : 대부분의 경우에 대한 Phantom Read 방지
- 하나의 transaction 내에서 동일 레코드에 대해 일반 SELECT 후, SELECT .. FOR UPDATE 등을 수행하게 되면 Phantom Read가 발생할 수는 있다.
- Undo log + Undo log history + 갭락 + SELECT .. FOR SHARING : Serializable 격리 수준 달성
Non-Locking Consistent Read
InnoDB에서는 MVCC 기술을 이용해 잠금을 걸지 않고 읽기 작업을 수행
- Serializable 수준 외의 다른 격리수준에서는 일반 SELECT의 경우 다른 트랜잭션에서 잠금을 걸었더라도 잠금을 기다리지 않고 읽기 작업을 수행한다.
- 동시성 처리 능력이 상승
참고
real mysql8.0
MySQL :: MySQL 8.0 Reference Manual :: 15.7.2.1 Transaction Isolation Levels
[MySQL] 트랜잭션의 격리 수준(Isolation Level)에 대해 쉽고 완벽하게 이해하기
Lock으로 이해하는 Transaction의 Isolation Level
'MySQL' 카테고리의 다른 글
| Spring JPA MySQL skip locked 성능 최적화 - 선착순 쿠폰 발급 예제 (0) | 2024.05.09 |
|---|---|
| [Real MySQL] 쿼리 작성 및 최적화 2 (0) | 2024.05.06 |
| [Real MySQL] 쿼리 작성 및 최적화 1 (1) | 2024.05.06 |
| [Real MySQL] 인덱스 (0) | 2024.04.11 |
| [Real MySQL] 트랜잭션과 잠금 (0) | 2023.12.29 |