트랜잭션 격리 수준
여러 트랜잭션이 동시에 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나
조회하는 데이터를 볼 수 있게 허용할지 여부를 결정하는 것
필요성
DB는 ACID 특징과 같이 트랜잭션이 독립적인 수행을 하도록 하는데,
이 때, 다른 트랜잭션이 관여하지 못하도록 막아야 한다.
하지만, 무조건 Locking을 통해 수많은 트랜잭션을 순서대로 처리하게 되면 데이터 베이스의 성능이 저하
그렇다고 성능을 높이기 위해 Locking의 범위를 줄이면, 잘못된 값이 처리 될 가능성이 높아진다.
따라서, 최대한 효율적이 Locking 방법이 필요
격리 수준 4가지
- SERIALIZABLE (직렬화 가능)
- REPEATABLE READ (반복 가능한 읽기)
- READ COMMITTED (커밋된 읽기)
- READ UNCOMITTED (커밋되지 않은 읽기)
아래로 갈 수록 격리 수준이 낮아지며, 동시 처리의 성능이 높아지지만 데이터 부정합 문제가 발생할 확률이 높아진다
데이터의 정합성과 성능은 반비례
SERIALIZABLE (레벨 3)
- 데이터를 접근할 때 다른 트랜잭션이 접근 할 수 없도록 Lock
- SELECT 작업에서도 Shared Lock을 걸어 읽기만 가능하도록 한다.
- 가장 안전하지만 가장 성능이 떨어짐
REPEATABLE READ (레벨 2)
- 한 트랜잭션 내에서 특정 행을 조회시 항상 같은 데이터를 응답 하는 것을 보장
- MySQL과 MariaDB가 기본적으로 사용
- 일반적인 RDBMS는 변경전의 레코드를 UNDO 공간에 백업해둔다.
- 그러면 변경 전/후의 데이터가 모두 존재하는데, 동일한 레코드에 대해 여러 버전의 데이터가 존재한다고
하여 이를 MVCC (Multi-Version Concurrency Control, 다중 버전 동시성 제어) 라고 부른다.
- 한 트랜잭션을 조회하는 도중 데이터가 수정된 경우
UNDO로그를 통해 같은 결과를 얻게 된다.
즉, REPEATABLE READ는 어떤 트랜잭션이 읽은 데이터를 다른 트랜잭션이 수정하더라도 동일한 결과를 반환할 것을 보장해준다.
발생할 수 있는 문제
팬텀 리드 (Phantom Read)
Non-Repeatable Read의 한 종류로 조회해온 결과의 행이 새로 생기거나 없어지는 현상이다.
💡 예시
같은 테이블에 접근하는 여러개의 트랜잭션을 처리하고 있습니다.
그중 한 트랜잭션이 SELETE ~~ FOR UPDATE 을 사용하여 쓰기 잠금을 걸고 싶다고 가정합니다.
쿼리문에 따라, SELECT하려는 레코드에 쓰기 잠금을 걸어야 하는데, Undo 레코드에는 잠금을 걸 수 없습니다.
따라서 위와 같은 쿼리는 Undo 영역의 변경 전 데이터를 가져오는 것이 아니라 현재 레코드의 값을 가져오게 됩니다.
이렇게 레코드가 보였다 안보였다 한다고 해서 PHANTOM 이라고 합니다.
READ COMMITTED (레벨 1)
- 커밋이 완료된 데이터만 조회 가능
- 대부분의 RDB가 Default로 사용
발생할 수 있는 문제
- 팬텀 리드 (Phantom Read)
- Non-Repeatable Read
하나의 트랜잭션 내에서 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는
Repeatable Read 정합성에 어긋나는 것
반복 읽기를 수행 할 경우에 다른 트랜잭션의 커밋 여부에 따라 조회 결과가 달라질 수 있다.
이런 데이터 부정합 문제를 Non-Repeatable Read(반복 읽기 불가능)
💡
일반적인 경우에는 크게 문제가 되지 않지만, 하나의 트랜잭션에서 동일한 데이터를 여러 번 읽고 변경하는 작업이 금전적인 처리와 연결되면 문제가 생길 수 있다. 예를 들어 어떤 트랜잭션에서는 오늘 입금된 총 합을 계산하고 있는데, 다른 트랜잭션에서 계속해서 입금 내역을 커밋하는 상황이라고 하자. 그러면 READ COMMITTED에서는 같은 트랜잭션일지라도 조회할 때마다 입금된 내역이 달라지므로 문제가 생길 수 있는 것
READ UNCOMMITTED (레벨 0)
- 커밋하지 않은 데이터도 접근 가능
발생할 수 있는 문제
- 팬텀 리드 (Phantom Read)
- Non-Repeatable Read(반복 읽기 불가능)
- Dirty Read
어떤 트랜잭션의 작업이 완료되지 않았는데도, 다른 트랜잭션에서 볼 수 있는 부정합 문제
여기서 Rollback대신 Commit이라면 상관없지만, Rollback이라 문제가 생긴다.
id = 51인 데이터를 계속 처리하고 있을 텐데, 다시 데이터 조회시 결과가 존재하지 않는 상황이 생긴다.
이러한 상황은 상당한 버그를 초래할 가능성이 높다.
참고
[MySQL] 트랜잭션의 격리 수준(Isolation Level)에 대해 쉽고 완벽하게 이해하기
이번에는 트랜잭션 격리 수준(Isolation Level)에 대해 알아보도록 하겠습니다. 아래의 내용은 RealMySQL과 MySQL 공식 문서 등을 참고하여 작성하였으며, 모든 내용은 InnoDB를 기준으로 설명합니다. 해당
mangkyu.tistory.com
'CS' 카테고리의 다른 글
SQL Injection (0) | 2023.07.27 |
---|---|
Join (0) | 2023.07.27 |
트랜잭션 (0) | 2023.07.20 |
HTTP HTTPS (0) | 2023.07.13 |
TCP와 UDP (0) | 2023.07.13 |