MVCC

텐저린티·2023년 9월 2일
0

알쓸신잡

목록 보기
8/10
post-thumbnail

동시성 제어

  • DBMS가 다수의 사용자 사이에서 동시에 작용하는 다중 트랜잭션 상호간섭 작용에서 Database 를 보호하는 것
  • 락 기반 동시성 제어는 읽기 트랜잭션 끼리만 동시 접근 가능

  • MVCC 를 사용하면 동시성 제어가 읽기 ↔ 쓰기 트랜잭션 동시 접근 가능
    • 쓰기 트랜잭션 끼리 동시 접근하는 경우만 Block

MVCC

  • Multi Version Concurrency Control
  • 동시성 제어 방법 중 하나
  • 데이터에 접근하는 사용자는 접근 시점에 DB 스냅샷 읽음
    • 트랜잭션마다 본인만의 저장공간을 따로 갖고, commit 시 한 번에 DB 반영한다는 느낌
  • commit 된 데이터만 읽음
    • 스냅샷 데이터가 커밋될 때까지 다른 트랜잭션은 볼 수 없음
    • 다른 트랜잭션이 데이터를 삭제하거나 수정해도 영향 받지 않고 데이터 사용 가능
  • 일반적인 RDBMS 보다 매우 빠르게 작동
    • 락을 필요로 하지 않기 때문
  • 사용하지 않는 데이터가 계속 쌓이게 되므로 데이터를 정리하는 시스템 필요
  • 데이터 버전 충돌 시 앱 영역에서 이 문제 해결해야 함.
    • PostgreSQL + Repeatable Read 인 경우에 나중 트랜잭션이 롤백되면, 나중 트랜잭션을 재실행해야 함

Isolation 레벨 별 MVCC

Read Committed

  • Read 하는 시간을 기준으로 그 전 commit 된 데이터 읽음

Repeatable Read

  • 트랜잭션 시작 시간 기준으로 그 전에 commit 된 데이터 읽음
  • 데이터 읽을 때 특정 시점 기준으로 가장 최근 commit 된 데이터 읽음 → MySQL Consist Read
  • 데이터 변화(write) 이력 관리
    • 추가 저장 공간 필요
  • read 와 write는 서로를 block 하지 않음 → MVCC
  • MySQL, PostgreSQL 모두 같은 결과

Serializable

  • 결과 자체는 Repeatable Read 와 같은 결과
  • MySQL
    • MVCC 로 동작하기 보다 락으로 동작
  • PostgreSQL
    • SSI 기법이 적용된 MVCC 로 동작

Read Uncommitted

  • MVCC 는 committed 된 데이터 읽음
  • 해당 고립 레벨에서는 MVCC 적용 X
  • PostgreSQL 경우 Read Uncommitted 레벨 존재하지만 Read Committed 레벨처럼 동작

Lost Update 문제

PostgreSQL MVCC의 lost update 문제

  • first-updater-win
  • 먼저 update 한 트랜잭션이 commit 되면 나중 트랜잭션은 rollback
  • 트랜잭션마다 다른 isolation level 을 줄 수 있기 때문에 발생하는 문제
    • postgreSQL MVCC는 lost updaterepeatable read 만으로 해결 가능
    • 한 트랜잭션만 신경쓸 게 아니라, 관련된 트랜잭션의 고립레벨도 신경써줘야 함
      • 둘 다 Repeatable Read

MySQL MVCC의 lost update 문제

  • repeatable read 만으로는 해결 불가
  • Locking Read 필요 → consist read
    • 읽기를 하면서 쓰기 락을 걸어주는 기능

    • 결과적으로 쓰기 락이 걸려있으므로, 다른 트랜잭션에서 Locking Read 가 걸려있는 상황에서는 락을 얻을 수 없음

    • MySQL에서 Locking Read 는 isolation level과는 상관없이 가장 최근 commit 된 데이터 읽음

    • 종류
      - for update
      - 쓰기 락 = 배타 락
      - for share
      - 읽기 락 = 공유 락

      select balance from account where id = 'x' for update;

Write Skew 문제

  • 두 트랜잭션이 작업 대상이 다른 연관있는 두 데이터를 변경할 때 발생하는 동시성 문제
  • MySQL, PostgreSQL 양쪽 모두에서 발생 가능
  • 해결 방법
    • 둘 다 Isolation LevelSerializable 로 변경하면 해결
    • 둘 다 select for update / select for share 로 락을 걸어 해결 가능하지만, MySQL과 PostgreSQL 동작 방식이 다름
      • MySQL에서는 Locking Read
      • PostgreSQL 에서는 Repeatable Read 원칙 적용

MySQL

  • Repeatable Read Isolation Level
    • 트랜잭션에 Locking Read (for update) 걸기
    • 그럼 트랜잭션1이 commit 되어 락을 해제할 때까지 트랜잭션2는 블락 당함
    • 트랜잭션2는 Locking Read 덕분에 가장 최근 commit 된 데이터 반영받음
  • Serializable Isolation Level
    • Repeatable Read 와 유사
    • 트랜잭션의 모든 평범한 select 문은 암묵적으로 select for share 처럼 동작
      • 성능 때문에 select for update 말고 for share
      • 데드락 발생 가능성 더 높음
    • 이런 특성 때문에 MySQL 은 동시성 문제 대응에 MVCC 보다는 락 방식을 사용한다고 말함

PostgreSQL

  • Repeatable Read Isolation Level
    • for update, for share 기능 있으나, MySQL이랑 동작이 다름
    • PostgreSQL MVCCRepeatable Read Isolation Level 에서 적용받는 규칙 적용됨
      • 같은 데이터에 먼저 update 한 트랜잭션이 commit 되면 나중 트랜잭션은 rollback
      • 트랜잭션2는 롤백 후 다시 실행하면 됨
  • Serializable Isolation Level
    • SSI(Serializable snapshot isolation) 로 구현
      • 여전히 MVCC로 동작하면서 동시성 문제 해결
    • first-committer-winner
profile
개발하고 말테야

0개의 댓글