동시성 제어(Concurrency Control)
DBMS에서 동시성 제어는 동시에 데이터에 접근하는 여러 사용자, 즉 여러 트랜잭션의 상호작용에서 트랜잭션의 isolation을 보장하고 일관성과 무결성을 유지할 수 있도록 하는 목적으로 사용되는 기술이다.
이러한 동시성 제어를 하는 대표적인 방식 중 가장 대표적인 Lock을 간단하게 알아보자.
공유 잠금(읽기 잠금, shared lock)이나 배타적 잠금(쓰기 잠금, exclusive lock)을 통해 Lock을 획득한 후 트랜잭션 내부의 작업을 수행하는 방식이다. (read로도 쓰기 잠금을 획득할 수 있다) 다른 트랜잭션은 이전 트랜잭션에서 Lock을 반환해야 작업이 수행이 가능하다는 의미이다.
이는 곧 SERIALIZABLE하다는 의미이며, 읽기 작업과 쓰기 작업이 서로 방해를 일으키기 때문에 병목 지점이 발생하며 데드락과 같은 동시성 문제가 발생할 수도 있다.
동시성을 제어하는 이유는 DML의 데이터 무결성을 보장하면서, 트랜잭션의 수를 최대화하는데 있다. 하지만 Lock을 사용한 동시성 제어에는 SERIALIZABLE하다는 특성 때문에 Lock이 커밋/롤백될 때까지 기다려야 한다. 이로 인해 동시 요청 처리 속도가 상당히 떨어지게 된다. 이를 해결하기 위해 등장한 방식이 MVCC이다.
MVCC(다중 버전 동시성 제어 - Multi Version Concurrency Control)
MVCC는 Lock과 같이 동시성을 제어하기 위해 사용하는 방법 중 하나이다.
MVCC는 쓰기 작업이 진행중인 레코드에 대해 원본과 변경 중인 데이터를 동시에 유지하는 방식이다. 원본 데이터에 대한 스냅샷(Snapshot)을 백업하여 보관한다. 이 스냅샷을 이용해 하나의 레코드에 대해 여러 버전을 관리하며, 데이터에 대한 변경 사항이 반영되기 전까지 다른 사용자가 변경 사항을 볼 수 없도록 보장한다.
MySQL에서는 Undo Log라는 롤백 세그먼트(백업 공간)을 통해 스냅샷을 구현한다. 데이터 변경 요청이 들어오면 변경된 레코드의 이전 정보를 Undo Log에 저장한다. 이 롤백 세그먼트를 통해 트랜잭션 롤백에 필요한 실행 취소 작업을 수행한다. 마찬가지로 변경 사항이 반영되기 전에 데이터를 읽더라도 이 Undo Log를 활용하여 일관된 읽기(Consistent Read)를 수행한다.
이러한 MVCC는 Lock을 필요로 하지 않기 때문에 일반적인 RDBMS보다 매우 빠르게 작동한다. 또한 롤백 세그먼트를 활용해 데이터를 읽기 시작할 때 누군가 데이터를 변경하더라도 영향을 받지 않는다. 하지만 메모리 영역에 사용하지 않는 공간이 계속 늘어나게 되므로 데이터를 정리하는 작업이 필요하다. 하나의 레코드, 데이터에 대한 여러 버전이 생길 수 있기 때문에 데이터 버전 충돌 시 애플리케이션 영역에서 해결해야한다.
참조
https://dev.mysql.com/doc/refman/8.4/en/innodb-multi-versioning.html
https://www.youtube.com/watch?v=0PScmeO3Fig&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=18
2023.04 ~ 백엔드 개발자의 기록
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!