~/tech-blog/posts/mvcc — zsh

MVCC (multiversion concurrency control)

기존 Lock 기반 방식

read write
read O X
write X X

기존 컨커런시 컨트롤러는 위와 같이 read만 동시에 동작할 수 있기 때문에, read와 write가 동시에 발생하는 경우에는 대기하고 기다리게 됩니다. 이 때문에 동시에 처리하게 될 때 성능적으로 떨어지게 됩니다. 이를 해결하기 위해 MVCC가 등장하게 되었습니다.

MVCC

같은 데이터에 대해서

read write
read O O
write O X

양쪽 트랜잭션에서 write가 발생하는 경우에는 block되지만, 그 외의 경우에는 동작합니다. 이를 토대로 동시에 처리하는 성능이 올라가게 되는 것입니다.

  1. 트랜잭션 1은 유저의 권한을 읽습니다.
  2. 트랜잭션 2는 유저의 권한을 최고권한으로 변경합니다.
    1. 트랜잭션이 동작될 때 해당 값으로 변경되기 전에 write lock의 권한을 부여받습니다.
    2. 권한을 부여받으면 변경하려는 커밋 직전의 값(최고권한)을 따로 저장해둡니다.
  3. 트랜잭션 2가 write를 했지만 아직 커밋하지 않은 상태에서 트랜잭션 1이 해당 유저의 데이터를 읽으면 어떤 값을 읽게 될까요?
    1. 최종 커밋된 데이터를 읽게 됩니다. → 일반권한으로 읽게 되는 것입니다.

💡 즉 MVCC는 커밋된 데이터만 읽는다는 것입니다.

  1. 이제 트랜잭션 2가 커밋을 하게 되었습니다.
    1. 자체적으로 저장해두었던 최고권한 값이 데이터베이스에 반영됩니다.
    2. 2-a에서 부여받은 write lock 값이 unlock으로 회수됩니다.
      1. 여기서 왜 unlock으로 DB가 자체적으로 권한을 회수하는지 의문을 품을 수 있습니다. 이는 트랜잭션이 작동될 때 문제가 발생하면 롤백을 시켜주기 위해 해당 기능이 동작하는 것입니다. 따라서 recoverability를 위해 커밋할 때 write lock을 unlock 해줍니다.
  2. 여기서 트랜잭션 1이 해당 유저의 값을 읽는다면 어떻게 될까요?
    1. 여기서는 트랜잭션의 isolation level 값에 따라 다르게 읽게 됩니다.
      1. isolation level이 read committed라면 read하는 시간을 기준으로 그전에 commit된 데이터를 읽습니다. ⇒ 즉 최고권한 데이터를 읽게 된다는 것입니다.
      2. isolation level이 repeatable read라면 트랜잭션 시작 시간을 기준으로 그전에 commit된 데이터를 읽습니다. ⇒ 즉 기본권한 데이터를 읽게 됩니다.
      3. isolation level이 read uncommitted라면 MVCC는 commit된 데이터를 읽기 때문에 이 레벨에서는 보통 MVCC가 적용되지 않습니다.

MVCC

  • 데이터를 읽을 때 특정 시점 기준으로 가장 최근에 commit된 데이터를 읽습니다. ⇒ Consistent read
  • 데이터 변화(write) 이력을 관리합니다. ⇒ 추가적인 저장 공간을 더 사용하는 것이 단점이지만, 동시성 측면에서는 장점이 있습니다. 이 때문에 오늘날의 데이터베이스는 MVCC를 사용해서 만들어집니다.
  • read와 write는 서로를 block하지 않습니다.

댓글

GitHub 계정으로 로그인하시면 댓글과 질문을 남기실 수 있습니다. 남겨 주신 글은 이 저장소의 Discussions에 쌓입니다.

● main 214 posts UTF-8 LF © 2026 코징 RSS · GitHub