해당 내용은 쉬운코드님의 영상을 기반으로 제작되었습니다
😓 다양한 트랜잭션 문제 예시와 해당 문제의 이름
♪ Dirty read
트랜잭션 1 : x에 y의 값을 더한다
트랜잭션 2 : y 의 값을 70으로 바꾼다
이전 데이터 ▶ x = 10, y = 20
- 상황
- 1번이 실행이 되면 처음에 x의 10을 읽었는데 2번이 실행되었다. 2번은 y를 70으로 바꾸었다. 그리고 1번이 쭈욱 실행이 되고 y가 70이 되었기 때문에 x에 80이라는 숫자로 commit 을 해주고 종료되었다. 하지만 2번이 문제가 발생하면서 y의 데이터가 rollback이 되었다.
이후 데이터 ▶ x = 80, y = 20
정의
commit 되지 않은 변화를 읽은 것처럼 나타나는 것이 Dirty Read 이다
♪ Dirty Read ( 2 )
트랜잭션 1 : x가 y에 40을 이체한다
트랜잭션 2 : x와 y를 읽는다
이전 데이터 ▶ x = 50, y = 50
- 상황
- 1번이 x를 읽고 40보다 많으면 가격을 뺀다. 그리고 2번이 x와 y를 읽는다. commit을 하고 종료한다. 1번은 y에 40을 더해주고 commit 을 해준다.
- 이때 원래 데이터의 합(총량)은 100인데 2번 트랜잭션이 읽는 순간은 60이기 때문에 문제가 있다
이후 데이터 ▶ x = 10, y = 90
♪ Non-repeatable read (Fuzzy Read)
트랜잭션 1 : x를 두번 read한다
트랜잭션 2 : x에 40을 더한다
이전 데이터 ▶ x = 10
- 상황
- 1번이 x를 읽고 2번도 동작을 시작한다. 2번은 x를 50으로 전환하고 commit 한다. 이어서 1번이 x를 한번 더 읽고 commit 한다. 이때 읽는 두개의 숫자가 다른다 첫번째로 읽은 x의 데이터는 10이고 두번째로 읽은 데이터는 50이다.
- 같은 데이터를 같은 트랜잭션에서 읽어서 가져왔는데 값이 다르다는 것은 Isolation 관점에서는 발생해서는 안된다 왜냐하면 각각의 트랜잭션은 동시에 실행되지만 마치 혼자서 실행되는 것 같이 보여야 하는데 값이 다르기 때문이다.
이후 데이터 ▶ x = 50
정의
같은 트랜잭션에서 같은 값을 읽었는데 값이 변경되었다.
♪ Phantom read
트랜잭션 1 : v가 10인 데이터를 두번 읽는다
트랜잭션 2 : tuple2 의 v를 10으로 변경한다
이전 데이터 ▶ tuple1 (v = 10), tuple2 (v = 50)
- 상황
- 1번이 v가 10인 데이터를 읽는다. 그리고 2번이 시작되고 2번은 tuple2의 v값을 10으로 바꾼다. 그리고 이어서 1번이 한 번더 v가 10인 데이터를 읽는데 이때 첫번째와 달리 tuple1과 tuple2를 읽는다. 같은 트랜잭션에서 같은 조건으로 읽었는데 데이터가 다른건 위에서도 말했지만 Isolation하지 않다고 했다.
이후 데이터 ▶ tuple1 (v = 10), tuple2 (v = 10)
정의
Fuzzy Read 와 비슷하지만 없던 데이터가 생겨난 것이 다르다.
♪ Phantom read ( 2 )
트랜잭션 1 : v > 10 데이터와 count를 읽는다.
트랜잭션 2 : v = 15인 tuple을 추가하고 count를 1 증가시킨다.
이전 데이터 ▶ tuple1 (v = 7), count = 0
※ 제약사항 : Count 는 v > 10 인 tuple의 갯수를 저장한다.
- 상황
- 1번이 v > 10인 곳을 읽는다. 2번이 자신의 일을 한다. 그리고 count 를 올리고 commit 한다. 1번은 count 의 값을 읽고 1인것을 확인하고 commit 한다.
- 이는 1번 트랜잭션의 조건인 v > 10 인 tuple의 갯수가 아닌것이다. 앞서 읽을떄는 10을 넘는 tuple이 없었는데 갑자기 생겨난 것이다.
이후 데이터 ▶ tuple1 (v = 10), tuple2 (v = 15), count = 1
♪ Dirty Write
트랜잭션 1 : x를 10으로 바꾼다
트랜잭션 2 : x를 100으로 바꾼다
이전 데이터 ▶ x = 10
- 상황
- 1번이 x를 10으로 바꾸고 2번 트랜잭션이 x를 100으로 바꾸었다. 근데 트랜잭션1번이 문제가 발생해서 0으로 돌려야 하는데 이때 2번이 한 행위도 rollback해야 한다. 근데 2번이 데이터를 rollback하면 0이 아니라 10으로 가게 된다.
이후 데이터 ▶ x = 10?? 0??
정의
commit 이 되지 않은 데이터를 write하는 경우
rollback시 정상적인 recovery는 매우 중요하기 떄문에 모든 isolation level에서 dirty write는 허용해서는 안된다
♪ Lost Update
트랜잭션 1 : x를 50을 더한다
트랜잭션 2 : x를 150을 더한다
이전 데이터 ▶ x = 50
- 상황
- 1번이 x의 값을 읽고 2번도 x의 값을 읽는다. 2번은 x의 값을 200으로 바꾸는데 1번이 읽은값이 50이기에 100이 된 후로 commit을 하면서 200의 값이 사라진다
이후 데이터 ▶ x = 100
♪ Read skew
트랜잭션 1 : x가 y에 40을 이체한다
트랜잭션 2 : x와 y를 읽는다
이전 데이터 ▶ x = 50, y = 50
- 상황
- Dirty read와 비슷한 상황이다. 하지만 이번에는 2번이 x를 읽는 것으로 먼저 시작을 한다. x의 값 50을 읽고 1번이 x값을 빼고 y의 값에 더해준다. 그리고 2번 트랜잭션이 y를 읽으면 두개의 숫자가 또 총량과 다르다는 것을 알 수 있다
- 만약 2번이 읽은 데이터가 x와 y처럼 다른 두개의 값이 아닌 x한개라면 fuzzy read와 같은 꼴이 되는 것이다.
이후 데이터 ▶ x = 100
정의
inconsistent 한 데이터 읽기
♪ Write skew
트랜잭션 1 : x에서 80을 인출한다
트랜잭션 2 : y에서 90을 인출한다
이전 데이터 ▶ x = 50, y = 50
※ 이때 x + y >= 0 의 제약사항을 두고 진행을 한다.
- 상황
- 1번이 x와 y를 읽는다. 2번도 값을 확인한다. 1번은 80을 인출한다. 2번도 y에서 90을 인출한다 그리고 1번이 commit 하고 2번도 commit 을 하지만 결과는 또다시 제약사항을 깨는 상황이 발생한다.
이후 데이터 ▶ x = -30, y = -40
정의
inconsistent 한 데이터 읽기
😓 너무 많은 상황 그에 따른 제약사항
우리가 지켜야할 이상 현상들이 너무 많다 그렇다면 이러한 제약사항을 다 지키는게 과연 좋은 상황일까?
- 제약사항이 많아지는 것은 동시 처리 가능한 트랜잭션의 수가 줄어들게 되어 결과적으로 DB의 전체 처리량이 하락하는 경우가 생기게 된다
그로 인해 우리는 모든 제약을 지키는 것이 아닌 일부만 지키는 Level을 만들게 되었다.
- 밑의 사진은 가장 대표적으로 나타나는 트랜잭션의 문제 3가지를 대표로 뽑아 level을 정하고 위에서 다루는 내용은 훨씬 많다. 그 이유는 트랜잭션의 문제는 이 3가지로 isolation의 문제를 모두 대변할 수 없기 때문이다.
😓 SnapShot Isolation
- 기존에 표준에서 정의한 level과는 조금 다르다. 이상 현상 3가지를 얼마나 포용하느냐에 따라 level을 나눈 표현에 반해 "동시성 제어를 어떻게 구현할지"를 바탕으로 정의되었다.
동작 방법
트랜잭션 1 : x가 y에게 40을 이체한다
트랜잭션 2 : y 가 자신에게 100을 입금한다
이전 데이터 ▶ x = 50, y = 50
※ snapshot에 의한 관리 : 특정 시점(트랜잭션의 시작 지점)에서의 현상
- 상황
- 1번이 x의 값을 읽는다. x에서 40을 뺀다. 이때 snapshot에 데이터를 작성하고 db에서는 값을 유지한다.
- 2번이 y를 읽고 50을 파악한다. 이때 2번의 snapshot이 생기고 거기에 y의 값을 작성하고 100을 입금한다. 그리고 snapshot에도 데이터를 저장한다. 그리고 commit 을 하여 마무리하고 snapshot에 적힌 내용을 db로 넘긴다
- 1번은 y의 값을 읽어야 하는데 이때 DB의 값을 보는것이 아니라 snapshot이 생성된 시점인 맨 처음 데이터를 가져왔을때를 읽는다. 때문에 y를 50으로 인지하고 거기에 40을 더해준다
- 이때 1번과 2번은 같은 데이터를 write하고 있다. 때문에 여기서 1번을 바로 commit 해주지 않고 1번을 rollback해준다.
- 뭔가 이상하지만 여기까지만 알아보고 이후에 더욱 자세히 알아볼 예정이다.
이후 데이터 ▶ x = 50, y = 150
정의
MVCC(multi version concurrency control) 타입이다
트랜잭션이 시작되었을때 commit 된 데이터만 보인다.
그리고 처음으로 commit 한 놈이 승리다.
MVCC 는 이후에 더 깊게 공부를 할 예정이다.
'CS > 💾 DB' 카테고리의 다른 글
💾 MVCC, 트랜잭션 ( 5 ) (feat. MySQL과 PostgreSQL 비교) (1) | 2024.04.27 |
---|---|
💾 LOCK을 활용한 트랜잭션( 4 ) (1) | 2024.04.26 |
💾 Concurrency control의 기초, 트랜잭션 ( 2 ) (0) | 2024.04.23 |
💾 Transaction, 트랜잭션이란? (0) | 2024.04.23 |
💾 ORM이란? (0) | 2023.09.16 |