일반적으로 MySQL은 MVCC라고 한다
하지만 조금 더 정확히 얘기하면 isolation level에 따라 다른데,
read commiited와 repeatable read는 MVCC라고 하지만
read uncommitted와 serializable은 MVCC가 아니라고 얘기한다
MySQL의 serializable 레벨은 MVCC가 아닌가?
MySQL에서 serializable 레벨은 MVCC가 아닌 lock으로 동작한다
공식 문서에서 serializable 레벨을 아래와 같이 설명하고 있기 때문이다
This level is like REPEATABLE READ,
but InnoDB implicitly converts all plain SELECT statements to SELECT ... FOR SHARE
if autocommit is disabled.
이 문서에서 말하는 것은 MySQL이 serializable 레벨일 때는 transaction 내에서 평범한 select 문을 사용해도 해당 select 문을 SELECT ... FOR SHARE로 암묵적으로 바꿔서 처리한다는 것이다
SELECT ... FOR SHARE는 select를 할 때 read lock을 먼저 획득하도록 하는 쿼리문이다
한편, MySQL에서 insert, update, delete 같이 DB를 변경(write)하는 쿼리 문을 실행하면 기본적으로 해당 tuple에 대해서 write lock을 먼저 획득한 뒤에 해당 쿼리 문을 수행한다
그런데 MySQL의 serializable 레벨에서는 평범한 select 문도 read lock을 획득하게끔 만들기 때문에, 결과적으로 read/write 모두 lock을 쓴다고 볼 수 있고, 이것은 MVCC 방식과는 상충된다
왜냐하면, MVCC의 기본 목적은 (쉽게 설명하면) read lock을 쓰지 않음으로써, 서로 다른 트랜잭션들이 같은 tuple에 대해서 read/write 혹은 write/read 하더라도 서로를 블락(block) 하지 않도록 하는 것인데, MySQL에서 serializable 레벨은 select에서도 read lock을 사용하기 때문에, 이 레벨은 MVCC로 동작한다고 보기 어렵기 때문이다
MySQL에서는 모든 lock은 트랜잭션이 rollback 혹은 commit 될 때 반환되기 때문에,
오히려 MySQL의 serializable 레벨은
MVCC가 아니라 lock 기반의 SS2PL로 동작한다고 볼 수 있겠다
번외편으로..
read uncommitted는 MVCC 인가?
MySQL 공식 문서에 아래와 같은 얘기가 있다
READ UNCOMMITTED
SELECT statements are performed in a nonlocking fashion,
but a possible earlier version of a row might be used.
Thus, using this isolation level, such reads are not consistent.
This is also called a dirty read.
Otherwise, this isolation level works like READ COMMITTED.
MySQL 세계관에서는 MVCC가 적용된 read를 consistent read 라고 하는데, 위의 매뉴얼에 따르면 not consistent 라고 되어 있는 것으로 봐서는 read uncommitted 레벨일 때는 MVCC가 적용되지 않음을 알 수 있다
어떻게 보면 당연한 것인데 MVCC의 동작 원리가 read를 할 때 commit 된 데이터만 읽기 때문에 기본적으로 read committed 레벨부터 적용될 수 있는 기법이기 때문이다
쉬운코드는 기본에 진심입니다
👉 isolation level 영상 보러 가기
👉 Lock & SS2PL 영상 보러 가기
👉 MVCC 1부 영상 보러 가기
👉 MVCC 2부 영상 보러 가기