[영상후기] (1부) DB MVCC 개념 설명합니다 ! MVCC가 각각의 isolation level에서 어떻게 동작하는지도 MySQL & postgreSQL 예제와 함께 설명합니다

박철현·2023년 4월 12일
0

영상후기

목록 보기
89/160

movie

  • MVCC(multiversion concurrency control)

    • 같은 데이터에 대해 서로 다른 트랜잭션이 write-write 하는 경우는 한쪽이 block되지만, 그 외의 경우는 동시에 처리 가능(Read-write 등 가능)
    • MVCC는 commit된 데이터만 읽음
    • Isolation level에 따라 읽는 방법이 다름
      • read committed : read하는 시간 기준 그전에 커밋된 데이터를 읽는다
      • repeatable read : 트랜잭션 시작 시간 기준으로 그전에 commit된 데이터를 읽는다(사용하는 RDBMS에 따라 다를 수 있음)
      • serializable : repeatable read와 동일한 결과
        • MySQL : Lock 기반 동작
        • PostgreSQL : SSI(Serializable Snapshot Isolation) 기법이 적용된 MVCC로 동작
      • read uncommitted : MVCC 적용되지 않음
        • 보통 committed된 데이터를 읽기 때문
        • MySQL은 없음, postgreSQL은 read committed level처럼 동작함
  • MVCC

    • 데이터 읽을 때 특정 시점 기준(Isolation level 마다 다름) 가장 최근에 commit된 데이터를 읽는다. -> MySQL에서는 Consistent read라 함
    • 데이터 변화(write) 이력을 관리한다.
      • 특정 시점 기준이므로 (추가적 저장공간 필요)
      • read와 write는 서로 block 하지 않는다.
      • 성능면에서 동시에 처리할 수 있는 트랜잭션 증가, 대부분 RDMS 해당 방식 사용

Postgre SQL MVCC 예제 1

x = 50 / y = 10
트랜잭션 1 : x가 y에 40을 이체
트랜잭션 2 : x에 30 입금
Postgre SQL은 snapshot 방식으로 MVCC 동작

  • 정상 동작 할 경우 : x = 40 / y = 50
  • 트랜잭션 1, 2 모두 Read Committed로 가정
  • 트랜잭션 1이 먼저 실행된다 가정
  • 순서
      1. 트랜잭션 1에서 read(x) => 50
      1. 트랜잭션 1의 snapshot에서 x=10으로 작성 write(x=10)
      1. 트랜잭션 2에서 x를 읽기, read(x) => 50
      1. 트랜잭션 2에서 30입금 -> write(x=80) -> 트랜잭션1에서 write lock을 가지고 있어 대기
      1. 트랜잭션 1에서 read(y) => 10
      1. 트랜잭션 1에서 snapshot에 write(y=50)
      1. commit(snapshot 반영) (x->10 / y -> 50)
      1. 트랜잭션 2에서 x에 대한 lock 획득 후 snapshot에 x갱신, write(x=80)
      1. 트랜잭션 2 commit (x->80)
        Lost Update 발생(x에서 40을 빼는 update 무시)

해결 : 트랜잭션2의 Isolation level을 Repeatable Read로 변경

  • Postgre SQL에서 Repeatable Read의 특성은 first-updater-win의 특징을 기짐
    • first-updater-win : 같은 data에 먼저 update된 Transaction이 commit되면 나중 Transaction은 rollback
  • 위 과정에서 8번 부분에서 write(x=80)이 실패함
    • first-updater-win 적용되어 x값이 이미 commit이 되었기 때문
  • 이후 롤백되어 최종 결과는 x=10, y=50이 되고, 다시 트랜잭션2를 실행하면 정상적인 결과를 얻을 수 있음

Postgre SQL MVCC 예제 2

x = 50 / y = 10
트랜잭션 1 : x가 y에 40을 이체
트랜잭션 2 : x에 30 입금
Postgre SQL은 snapshot 방식으로 MVCC 동작

  • 정상 동작 할 경우 : x = 40 / y = 50
  • 트랜잭션 1은 Read Committed / 트랜잭션 2는 Repeatable Read 설정
  • 트랜잭션 2가 먼저 실행된다 가정
  • 순서
      1. 트랜잭션 2가 먼저 x를 읽는다, read(x) => 50
      1. 트랜잭션 1이 x를 읽는다, read(x) => 50
      1. 트랜잭션 2가 x값을 갱신한다. write(x=80) / lock획득
      1. 트랜잭션 1이 x값을 갱신한다. write(x=10) -> lock이 없어 대기
      1. 트랜잭션 2가 commit 후 lock 반환(DB x = 80 갱신)
      1. 트랜잭션 1이 못했던 4번을 실행. write(x=10)
      1. 트랜잭션 1이 y를 읽는다. read(y) => 10
      1. 트랜잭션 1이 y값 갱신. write(y=50) => lock획득
      1. 트랜잭션 1이 commit하여 DB 갱신(x = 10, y = 50)
        **Lost Update 발생(트랜잭션 2의 x 갱신 update)

해결 : Transaction 1의 Isolation Level을 Repeatable Read로 변경

  • 위 과정에서 6번을 수행할 때 rollback 발생
    • first-updater-win 속성 때문
  • 따라서 최종 결과는 x=80, y=10으로 트랜잭션 1을 다시 실행 시 정상적인 결과를 얻을 수 있음

결론

  • LOST UPDATE : MVCC로 진행하다 LOCK에 의해 업데이트가 반영 안된 것

    • isolation level 변경으로 해결할 수도 있다.
      • read committed -> repeatable read
      • postgreSQL에서 repeatable read의 경우 first-updater-win의 특징을 가지고 있다.
        • 같은 데이터에 먼저 update한 트랜잭션이 커밋하게되면 나중 트랜잭션은 롤백
        • 양쪽 x를 write하려 시도 -> 한쪽 커밋, 한쪽 롤백 -> 한쪽만 성공) -> rollback이니 다른 쪽에서 다시 재시도를 하면 성공
  • 트랙잭션마다 서로 다른 isolation level 줄 수 있음

  • 한 트랜잭션의 Isolation level만 챙기는 것이 아니라 양쪽 모두 신경 써야함

  • MySQL에서는 같은 데이터에 먼저 update한 트랜잭션이 커밋하게되면 나중 트랜잭션은 롤백되는 경우가 없음

    • first-updater-win가 존재하지 않음
    • LOST UPDATE 존재
  • MySQL에서 해결방법은 2부에

profile
비슷한 어려움을 겪는 누군가에게 도움이 되길

0개의 댓글

관련 채용 정보