본문 바로가기
스터디/MySQL

MVCC(Multi Version Concurrency Control)

by Big Sun 2024. 11. 27.
728x90

 

MVCC는 일반적으로 레코드 레벨의 트랜잭션을 지원하는 DBMS가 제공하는 기능입니다.

 

Multi Version Concurrency Control(MVCC)을 직역하면 '다중 버전 동시성 제어'입니다. 이 표현에서 유추할 수 있는 것은 'MVCC는 여러 버전이 존재하며, 동시성 제어와 관련이 있다'는 점입니다.

 

 

하나 이상의 버전이 존재한다?

하나의 레코드에 여러개의 버전이 동시에 관리됨을 의미합니다.

 

여러개의 버전이 왜 필요할까?

(READ_COMMITTED 격리 수준을 전제로)

한 레코드를 수정 중일 때, 해당 레코드를 조회하는 요청이 들어오면, 아직 수정 내용이 커밋되지 않았으므로 수정 전의 데이터를 조회해야 합니다.

또한, 하나의 트랜잭션에서 레코드를 수정한 뒤 다른 작업 중 에러가 발생하면 기존 데이터로 롤백이 이루어져야 합니다.

이러한 상황을 효율적으로 처리하기 위해 InnoDB는 언두 로그(Undo log)를 활용하여 데이터를 버전별로 관리합니다.

 

InnoDB 버퍼 풀과 언두 로그

 

   1. INSERT 문이 실행되어서 InnoDB 버퍼 풀과 디스크에 m.id = 12인 레코드가 저장되었습니다.

 

   2. UPDATE문이 실행되어, m.area가 서울에서 경기로 업데이트 되었습니다.

 

 

아직 커밋되지 않았으므로 디스크에 최종 반영되지 않습니다. 또한, UPDATE 문은 InnoDB 버퍼 풀에만 반영되며, 수정 전의 레코드는 언두 로그에 저장됩니다. 마지막으로, 데이터 파일에는 UPDATE 문이 반영되어 있을 수도 있고, 아닐 수도 있습니다.

이렇게 InnoDB에서는 3가지 버전으로 레코드를 관리하고 있습니다.

 

데이터 변경 및 조회 예시

 

위에서 언급했던 한개의 레코드를 수정하고 있는 도중 해당 레코드에 대한 조회가 들어오는 상황을 예시로 들어보겠습니다. 조회가 들어오면 격리 수준에 따라 InnoDB 버퍼 풀 버전의 레코드를 가져올 수도 있고, 언두 로그 버전의 레코드를 가져올 수도 있습니다. 격리수준이 READ_COMMITED일 경우에는 언두 로그 버전의 레코드를 가져옵니다.

(격리 수준이 READ_UNCOMMITED라면 InnoDB 버퍼 풀 버전의 레코드를 조회합니다.)

 

위 예시에서 알 수 있듯이 하나의 레코드에 여러가지 버전을 관리하면 UPDATE 명령 직후 SELECT 명령이 오더라도 격리 수준에 따라 특정 버전을 선택하여 SELECT 명령을 처리할 수 있습니다.

 

롤백 예시

 

다음으로 언급했던 한 트랜잭션에서 한개의 레코드를 수정하고 또 다른 작업을 할 때 에러가 터진 경우 기존의 데이터로 롤백되는 상황을 예시로 들어보겠습니다.

 

   1. UPDATE문 실행되어 m.area가 서울에서 경기로 업데이트 되었습니다.

   

   2. 에러가 발생해 기존 데이터로 롤백이 됩니다.

 

 

언두 로그의 m.id = 12인 레코드 데이터를 사용해 InnoDB 버퍼 풀의 m.id=12의 데이터를 복구하고 언두 로그의 내용을 삭제합니다.

위 예시처럼 하나의 레코드에서 여러 버전을 관리하면, 롤백 발생 시 데이터를 손쉽게 복구할 수 있습니다.

 

 

MVCC를 사용하지 않고 해당 레코드에 잠금을 걸었다고 가정해보자

 

'하나의 레코드에 여러 버전이 존재하지 않고, 해당 레코드에 잠금을 걸어 수정이 완료될 때까지 조회할 수 없다고' 가정해봅시다.

DBMS에서 조회는 매우 중요한 역할을 합니다. 그러나 잠금을 사용한다면, 수정 중인 레코드를 조회하려 할 때 해당 레코드의 잠금이 해제될 때까지 대기해야 합니다.
InnoDB 스토리지 엔진은 MVCC를 도입하여 잠금을 사용하지 않고도 조회를 가능하게 합니다. 잠금을 걸지 않기 때문에 읽기 작업은 다른 트랜잭션의 잠금을 기다리지 않고, 언두 로그를 활용하여 수행됩니다.

즉, 순수한 읽기 작업은 대기 없이 바로 실행될 수 있습니다.



 

감사합니다!

 

출처 : Real MySQL 8.0

728x90