❒ Description
Lock을 활용한 concurrency control에서 Lock의 동작원리 및 특징에 대해서 학습했다.
하지만 Lock을 사용하여도 데이터의 일관성이 보장되지 않아 2PL이 등장하고, 2PL의 변형 모델도 학습했다.
그리고 Lock은 호환성이 좋지 않다는 점도 표로 확인했다. 호환성이 좋지 못하다는 것은 동시에 처리량이
좋지 못하다는 의미이다. 따라서 오늘날에는 이런 문제를 해결하기 위해 MVCC를 사용한다.
오늘은 MVCC가 무엇인지, 어떻게 동작하는지 알고있던 내용과 새롭게 알게된 내용을 학습하고 정리하자.
❒ MVCC (Multi Version Concurrency Control)
1. MVCC란?
MVCC도 Lock과 마찬가지로 Concurrency control을 구현한 기법 중 하나이다. 이 기법은 데이터를 읽을 때
특정 시점을 기준으로, 가장 최근에 commit된 데이터를 읽는다(Read-commited). 또한 MVCC는 Snap-shot을
사용하는 방식이기 때문에 기존의 데이터는 유지하고, 변경된 데이터는 Snap-shot에서 관리한다.
※ 참고 : read-uncommitted 레벨에서는 MVCC가 적용되지 않는다.
MySQL에서는 특정 시점을 기준으로 read를 하는 것을 Consistent read라고 한다.
참고로 read-committed 레벨에서는 read하는 시간을 기준으로 직전 commit된 데이터를 읽고,
repeatable-read 레벨에서는 트랜잭션 시작 시간을 기준으로 직전 commit된 데이터를 읽는다.
2. 장단점
MVCC는 lock을 거의 사용하지 않기 때문에 읽기 성능이 향상되며, 다른 트랜잭션에 영향을 받지 않는다.
그리고 기존의 lock 방식과는 다르게 read와 write는 서로 block하지 않기 때문에 동시에 처리할 수 있는
트랜잭션도 더 많아진다. 즉, 동시성이 향상된다. 또한 commit된 데이터만 읽기 때문에 Dirty Read,
Non-repeatable Read, Phantom Read 등의 문제를 방지하여 데이터의 일관성을 보장한다.
하지만, 단점도 존재한다.
snap-shot을 통해 데이터의 여러 버전을 관리하기 때문에 메모리 사용량이 증가할 수 있다. 이와 연결해서,
불필요해진 여러 snap-shot을 처리하기 위해 VACUUM, Garbage colloection 등이 추가적으로 필요할 수 있다.
3. 호환성
MVCC는 비잠금 방식의 읽기와 다중 버전 관리를 통해 읽기와 쓰기 충돌을 최소화하고, 높은 동시성을 제공한다.
또한 충돌을 처리하는 시점이 트랜잭션 종료 시점으로 지연되므로(낙관적 동시성 제어) 성능이 향상되며,
읽기 작업이 쓰기 작업에 의해 차단되지 않기 때문에 위와 같이 동시성을 극대화할 수 있다.
❒ 여전히 존재하는 Lost update & Write Skew
위 시나리오는 트랜잭션 A,B 모두 isolation level이 repeatable read로 동일하고, MVCC를 기반이다.
PostgreSQL의 경우에는 같은 데이터에 먼저 update한 트랜잭션이 commit되면 나중에 update를 시도하는
트랜잭션은 롤백되기 때문에 위와 같은 lost update 문제는 발생하지 않는다.
반면에 MySQL은 PostgreSQL과 같은 정책이 없기 때문에 위 시나리오 처럼 흘러가게 된다.
이 문제를 해결하기 위해서는 MVCC + 개발자의 개입이 필요하다.
❒ [MySQL] Lost update 해결하기
이 문제를 해결하기 위해서는 Locking Read를 사용하면 된다. Locking read을 사용하면 읽기를 할 때도
write-lock을 취득할 수 있다. 아래의 SQL문을 사용하면 Locking read를 할 수 있다.
SELECT ... FOR UPDATE;
SELECT ... FOR SHARE;
Locking read는 isolation level에 상관없이 무조건 가장 최근의 commit된 데이터만 읽는다.
그럼 이제 Locking read를 사용해서 lost update를 해결해보자.
Locking read를 사용하였기 때문에 트랜잭션A가 X를 읽을 때는, B가 update한 값을 읽게 된다.
이렇게 MVCC와 개발자의 개입(locking read)이 이루어지면 이러한 문제도 해결 가능하다.
❒ 회고
Concurrency Control은 여러 트랜잭션이 동시에 실행될 때 충돌을 방지하고 데이터 무결성을 유지하기 위한
방법론이다. 이 방법론을 실현하는 구체적인 기법에는 Lock, 2PL, MVCC 등이 있으며, 각각의 기법은 트랜잭션이
데이터에 접근하고 처리할 때 충돌을 어떻게 관리할지에 대한 동작 과정과 특징을 가지고 있다.
그리고 격리 수준(Isolation Level)은 이러한 동시성 제어 기법들이 얼마나 엄격하게 적용될지를 결정하며,
트랜잭션 간의 간섭을 얼마나 허용할지 설정하는 정책이다. 각 격리 수준은 데이터의 일관성과 성능 사이에서 균형을
맞추는 데 중요한 역할을 하며, 이는 상황에 따라 유동적으로 잘 선택해야 하는 개발작의 몫이다.
'CS > Database' 카테고리의 다른 글
Lock을 활용한 concurrency control (0) | 2024.10.02 |
---|---|
Isolation 레벨과 이상 현상들 (0) | 2024.09.26 |
DB Transaction & Concurreny Control (2) (0) | 2024.09.20 |
DB Transaction & Concurreny Control (1) (0) | 2024.09.12 |
B-tree와 DB 인덱스(index) (0) | 2024.09.01 |