본문 바로가기
DataBase

[DataBase]MVCC

by 올리브영 2023. 8. 4.
728x90
반응형

MVCC는 commit된 데이터만 읽는다.

  • 데이터를 읽을 때 특정 시점 기준으로 가장 최근에 commit된 데이터를 읽는다.
  • 데이터 변화 이력을 관리한다.
  • read와 write는 서로를 block하지 않는다.

MVCC 예제

x=10

Transaction1

  • x를 읽는다.

Transaction2

  • x를 50으로 바꾼다.

시작

  1. Transaction2에서 x를 50으로 바꾼다. write(x=50)
    1. 트랜잭션 2만 알 수 있는 공간에 x=50을 적는다.
  2. Transaction1에서 x를 읽는다. read(x) → 10
  3. Transaction2 commit → x = 50
  4. Isolation Level이 read committed라면
    1. Transaction1에서 x를 읽는다. read(x) → 50
  5. Isolation Level이 repeatable read라면
    1. Transaction1에서 x를 읽는다. read(x) → 10

MySQL에서 lost update 해결

x=50, y=10

Transaction1

  • x가 y에 40을 이체한다.

Transaction2

  • x에 30을 입금한다.

시작

  1. Transaction2에서 x를 읽는다. read(x) → 50
    1. SELECT balance FROM account WHERE id = ‘x’ FOR UPDATE
    2. read를 하면서 write lock을 취득할 수 있다.(Locking read)
  2. Transaction1에서 x를 읽는다. read(x) → 50
    1. SELECT balance FROM account WHERE id = ‘x’ FOR UPDATE
    2. read를 하면서 write lock을 취득할 수 있다.(Locking read)
  3. Transaction2에서 x에 30을 더한다. write(x=80)
  4. Transaction2 commit
  5. Transaction1에서 x를 읽는다. read(x) → 80
    1. 원래 repeatable read라면 트랜잰셕 시작전 값인 50을 읽어야 하는데, 트랜잭션2가 commit된 80을 읽고있다.
    2. locking read는 가장 최근의 commit된 데이터를 읽는다.
  6. Transaction1에서 x에 40을 빼준다. write(x=40)
  7. Transaction1에서 y를 읽는다. read(y) → 10
    1. SELECT balance FROM account WHERE id = ‘y’ FOR UPDATE
    2. read를 하면서 write lock을 취득할 수 있다.(Locking read)
  8. Transaction1에서 y를 50으로 바꾼다. write(y=50)
  9. Transaction1 commit

핵심

  • MySQL은 repeatable read라서 해결을 못했는데, locking read를 이용해 해결.
  • SELECT … FOR UPDATE; → write lock 획득
  • SELECT … FOR SHARE; → read lock 획득

repeatable read에서 write skew 문제

x=10, y=10

Transaction1

  • x와 y를 더해서 x에 쓴다.

Transaction2

  • x와 y를 더해서 y에 쓴다.

정상적으로 동작한다면 최종 결과는

  1. x = 20, y = 30
  2. x = 30, y = 20

둘 중 하나가 되어야 한다.

시작

  1. Transaction1에서 x를 읽는다. read(x) → 10
  2. Transaction1에서 y를 읽는다. read(y) → 10
  3. Transaction2에서 x를 읽는다. read(x) → 10
  4. Transaction2에서 y를 읽는다. read(y) → 10
  5. Transaction1에서 x에 10을 더해준다. write(x=20)
    1. x lock 획득
  6. Transaction2에서 y에 10을 더해준다. write(y=20)
    1. y lock 획득
  7. Transaction1 commit
  8. Transaction2 commit
  9. 최종 결과는 x = 20, y = 20이 나온다.

MySQL에서 write skew 문제해결

x=10, y=10

Transaction1

  • x와 y를 더해서 x에 쓴다.

Transaction2

  • x와 y를 더해서 y에 쓴다.

시작

  1. Transaction1에서 x를 읽는다. read(x) → 10
    1. SELECT balance FROM account WHERE id = ‘x’ FOR UPDATE
    2. Locking read 획득
  2. Transaction2에서 x를 읽으려고 한다. read(x)
    1. SELECT balance FROM account WHERE id = ‘x’ FOR UPDATE
    2. Locking read 획득을 기다림.
  3. Transaction1에서 y를 읽는다. read(y) → 10
    1. SELECT balance FROM account WHERE id = ‘y’ FOR UPDATE
    2. Locking read 획득
  4. Transaction1에서 x에 10을 더해준다. write(x=20)
  5. Transaction1 commit
    1. Transaction1에서 획득한 lock 반환
  6. Transaction2에서 x를 읽는다. read(x) → 20
    1. SELECT balance FROM account WHERE id = ‘x’ FOR UPDATE
    2. Locking read 획득.
  7. Transaction2에서 y를 읽는다. read(x) → 10
    1. SELECT balance FROM account WHERE id = ‘y’ FOR UPDATE
    2. Locking read 획득.
  8. Transaction2에서 y에 20을 더해준다. write(y=30)
  9. Transaction2 commit
  10. x = 20, y = 30

 

출처

https://www.youtube.com/watch?v=wiVvVanI3p4&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=19

https://www.youtube.com/watch?v=-kJ3fxqFmqA&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=20

728x90
반응형

'DataBase' 카테고리의 다른 글

[DataBase] Transactional Isolation Level  (0) 2023.08.03
[SQL] DDL(Data Define Language)  (0) 2023.03.08
[DB] 데이터베이스 기본개념  (0) 2023.03.08