TRANSACTION: ISOLATION LEVEL

이승주·2024년 3월 17일
0

DATABASE

목록 보기
3/4

!! 글을 읽기 전 필독 !!
DBMS 마다 격리 수준에 대한 내용이 다를 수 있으니 보다 정확하게 알기 위해서는 공식 문서를 확인해야 한다. 필자는 MySQL 에서 제공하는 격리수준을 기준으로 하였다. 참고로 MySQL의 기본 격리수준은 Repeatable Read이다.

📌 ISOLATION LEVEL: 트랜잭션 격리 수준

여러 트랜잭션이 동시에 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것이다.

  • 표준적으로 0~3 Level 총 4개가 존재한다.
  • Level이 올라갈수록 격리 수준이 높아지지만 성능이 떨어진다.
  • 데이터 정확성과 성능이 반비례하기 때문에 상황에 맞게 잘 선택해야함

📌 왜 트랜잭션 격리 수준이 필요할까?

Isolation Level에 대한 조정은, 동시성과 데이터 무결성에 연관되어 있음

  • Level 낮을 수록 동시성은 증가 데이터 무결성에 문제가 발생확률 증가
  • Level 높을 수록 동시성은 감소 데이터 무결성에 문제가 발생확률 감소

즉 상황에 따라 처리해야하는 데이터 특성이 다를 것이다. 따라서 트랜잭션 격리 수준을 각 Level로 나누어 상황에 따라 동시성이 높은 Level, 데이터 무결성이 높은 Level을 선택할 수 있게 하기위해 존재한다.


📌 Read Uncommitted (레벨 0)

  • SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리지 않는 계층
  • 트랜잭션에서 처리중이거나, 아직 Commit되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용하는 계층
  • 데이터 베이스의 일관성을 유지하는 것이 불가능함

발생할 수 있는 문제: DIRTY-READ

커밋되지 않은 수정중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생하는 현상

어떤 트랜잭션에서 아직 실행이 끝나지 않은 상황에서 다른 트랜잭션에 의한 변경사항을 보게되는 경우

상황 예시


1. DB에는 10만원을 가지고 있는 계좌가 있다.
2. Transaction A는 DB에 Read 요청을한다. ->계좌의 10만원 확인
3. Transaction A는 DB에 5만원 입금 Write 요청을한다. -> DB의 계좌는 15만원이 됨
4. Transaction A의 Commit은 완료되지 않았는데 Transaction B가 DB에 Read가 가능하다.
5. Transaction B는 15만원의 계좌금액을 확인한다.
6. 이 때 Commit이 완료되지 않은 Transaction A에 Rollback이 생겨 DB의 계좌는 10만원이 된다.
7. 즉 DB에는 10만원이 있는데 Transaction B는 15만원이 조회되는 DIRTY-READ 상황이 발생함

하지만 데이터가 잘 처리되어서 RollBack이 안 되었다면 동시에 데이터를 처리했기 때문에 빠른 성능을 보이게 되었을 것임, 즉 DB의 일관성, 고 신뢰성을 낮지만 성능은 높을 것을 확인할 수 있다.


📌 Read Committed (레벨 1)

  • SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리는 계층
  • 트랜잭션이 수행되는 동안 다른 트랜잭션이 접근할 수 없어 대기하게 하는 계층
  • Commit 이루어진 트랜잭션만 조회가능
  • Commit 완료된 데이터만 읽을 수 있기 때문에 DIRTY-READ문제를 해결할 수 있다.

발생할 수 있는 문제: NON-REAPEATABLE READ

트랜잭션 내에서 같은 데이터를 여러 번 조회할 때 읽은 데이터가 서로 다른 값으로 나오는 문제

상황 예시

1, DB에는 10만원을 가지고 있는 계좌가 있다.
2. Transaction A는 DB에 Read 요청을한다. ->계좌의 10만원 확인
3. Transaction A는 DB에 5만원 입금 Write 요청을한다. -> DB의 계좌는 15만원이 됨
4. Transaction A의 Commit은 완료되지 않아서 Transaction B는 Transaction A 실행 전 데이터인 10만원을 읽어 옴
5. Transaction A 가 Commit을 완료하고, Transaction B가 다시 Read하면 15만원을 읽어온다.
6. 즉 Transaction B는 같은 DATA를 읽기 요청을 헀는데 서로 다른 DATA가 나오며 문제 발생

여기서 헷갈렸는데 이해한 부분은 Transaction B내에서 Read 요청을 2번 이상 했을 때 다른 Data가 Read된다는 것이었다.


📌 Repeatable Read (레벨 2)

  • 트랜잭션이 완료될 때까지 SELECT 문장이 사용되는 모든 데이터에 Shared Lock이 걸리는 계층
  • 트랜잭션이 범위 내에서 조회한 데이터 내용이 항상 동일함을 보장하는 계층
  • 앞선 NON-REAPEATABLE READ의 상황 예시 5번에서 Transaction A가 Commit을
    완료해도 10만원을 읽어오게 함
  • 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정 불가능

발생할 수 있는 문제: Phantom Read

한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽었을 때, 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상

트랜잭션 도중 새로운 레코드 삽입을 허용하기 때문에 나타나는 현상임

상황 예시

  1. DB에는 10만원을 가지고 있는 계좌가 있다.
  2. Trasaction B가 은행계좌 수 조회를 하는 Read 쿼리를 날림 -> 계좌 갯수 1반환
  3. Transaction A가 새로운 계좌를 5만원이 들어있는 계좌를 생성
  4. 이후 Trasaction B가 은행계좌 수 조회하는 Read 쿼리 날림 -> 계좌 갯수 2반환
  5. 한 트랜잭션 에서 다른 값을 반환하게 됨

레코드가 추가된 상황에는 Repeatable Read가 적용되지 않아 동일한 값이 보장되지 않은 것임


📌 Serializable (레벨 3)

  • 트랜잭션이 완료될 때까지 SELECT 문장이 사용되는 모든 데이터에 Shared Lock이 걸리는 계층
  • 모든 Transaction들은 모두 순차적으로 실행하게 되는 계층임
  • 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정 및 입력 불가능


1. Transaction A Commit이 완료된다.
2. Transaction B가 실행된다.


📌 정리

Read Committed : 아직 커밋되지 않은 데이터를 읽을 수 있다.
Read Committed: 커밋된 데이터만 읽을 수 있다.
Repeatable Read: 특정 데이터를 반복조회시 같은 값을 반환한다.
Serializable: 트랜잭션이 순차적으로 실행된다.


참고자료

낮은 단계 Isolation Level을 활용할 때 발생하는 현상들

[10분 테코톡] 로건의 Transaction

정리의 표 참고

profile
반복되는 실수를 기록을 통해 줄여가보자!

0개의 댓글