"데이터베이스에 여러 명의 사용자가 접근할 때 어떻게 일관성 있는 데이터를 반환할 수 있을까?" 라는 물음에 대해 어떤 답변을 할 수 있을까요?
동시성을 제어하는 방법에는 아주 여러가지 다양한 방법이 있으나, 이번에는 DB에서 데이터의 동시성을 컨트롤하는 MVCC에 대해 알아보고자 합니다.
1. MVCC?
- Multi-Version Concurrency Control
- Lock을 이용한 동시성 제어 방법은 로직이 복잡하며 오버헤드가 많이 든다는 단점이 있음
- → lock을 이용하지 않고 동시성을 제어하고자 함
- 각 트랜잭션의 격리 수준을 이용
- 작동 방식 표준이 존재하지 않아 DB마다 상이함
- 특정 시점에 존재했던 데이터의 스냅샷을 이용해 작동함
- 트랜잭션은 실행 기간에 관계없이 데이터를 일관되게 볼 수 있음
- 트랜잭션마다 동일한 테이블에서 다른 데이터를 동시에 볼 수 있음
- 하나의 레코드에 대해 다양한 버전이 존재하게 됨
- 잠금 없는 읽기를 수행할 수 있게 됨
READ COMMITTED, REPEATEABLE READ 격리 수준에서만 작동함
2. InnoDB의 MVVC 구현 방식
ID 할당
- 트랜잭션이 시작된 후 데이터를 처음 읽을 때 id 할당
UPDATE
- 트랜잭션 내에서 레코드를 수정, 삭제하면 커밋 여부와 관계없이 버퍼풀은 변경된 내용으로 업데이트됨
- 기존 내용은 언두 로그에 언두 레코드로 기록됨
- 트랜잭션의 롤백 포인터가 해당 언두 레코드를 가리킴
- 언두 로그는 변경 내용을 되돌리는 방법을 설명함
- 리두 로그 처리됨
- 트랜잭션이 롤백을 해야 할 경우, 해당 포인터를 이용해 레코드를 복구함
💡 RollBack
언두 영역의 레코드를 버퍼 풀로 복구
언두 영역의 내용을 더 필요로 하는 트랜잭션이 없다면 언두 영역의 내용 삭제
SELECT
- 레코드의 transaction id와 읽기를 요청한 트랜잭션의 읽기 뷰를 비교함
- 변경된 트랜잭션이 아직 커밋되지 않은 경우, 요청한 트랜잭션이 볼 수 있는 트랜잭션 id에 도달할 때까지 언두 로그 레코드를 추적해서 적용함
- 롤백 포인터를 추적해서 언두 로그 체인을 거슬러 올라감
DELETE
- 레코드의
info flags에서 deleted 비트를 설정함 → soft delete
- 언두 로그에
remove deleted mark 기록
- 이후 purge thread가 어떤 트랜잭션도 참조하지 않는 언두 로그 공간과 마크된 레코드를 물리적으로 제거함

Reference