MySQL Isolation Level

목표

MySQL 의 Isolation Level 에 대해 알아보자.

Isolation Level

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE
  DIRT-READ NON-REPEATABLE READ PHANTOM READ
READ UNCOMMITTED O O O
READ COMMITTED X O O
REPEATABLE READ X X O
SERIALIZABLE X X X

READ UNCOMMITTED

READ UNCOMMITTED 는 dirty read 가 발생할 수 있다.

dirty read 란 다른 트랜잭션이 commit 되지 않은 데이터를 읽는 것을 말한다.

즉 A 트랜잭션에서 데이터 DATA-A 를 수정하고 commit 을 하지 않아도 B 트랜잭션에서 A 트랜잭션에서 변경한 DATA-A 를 읽을 수 있다.

READ COMMITTED

READ COMMITTED 는 dirty read 가 발생하지 않으며 consistent read 가 보장된다.

이와 같이 다른 트랜잭션과 다르게 데이터를 읽을 수 있는 이유는 undo log 를 사용하기 때문이다. 데이터를 변경하게 되면 undo log 에 변경 전 데이터를 저장하고 변경 후 데이터를 저장한다. 이때 다른 트랜잭션이 변경 전 데이터를 읽게 되면 undo log 에서 데이터를 읽게 된다.

READ COMMITTED 설정으로 인해 영향을 받는게 생긴다.

첫 번째로는 UPDATE, DELETE 를 사용할 때 레코드에 lock 을 걸게되는데 where 절이 실행되고 일치하지 않는 record 의 lock 을 해제하게 된다.

두 번째로는 UPDATE 할 때 해당 record 가 이미 lock 이 걸려있다면 최신 commit 버전 데이터를 읽는다. where 절에 일치하다면 record 를 다시 읽고 lock 또는 대기한다. 이를 semi-consistent read 라고 한다.

READ COMMITTED 는 NON-REPEATABLE READ 가 발생할 수 있다.

NON-REPEATABLE READ 란 같은 트랜잭션에서 같은 데이터를 읽었을 때 다른 결과가 나오는 것을 말한다.

  1. A 트랜잭션에서 WHERE name = ‘apeltop’ 을 조회한다. - 0 row
  2. B 트랜잭션에서 UPDATE set name = ‘apeltop’ 실행 후 commit 한다.
  3. A 트랜잭션에서 WHERE name = ‘apeltop’ 을 조회한다. - 1 row

REPEATABLE READ

REPEATABLE READ 는 READ COMMITTED 에서 발생하는 NON-REPEATABLE READ 가 발생하지 않는다. InnoDB 엔진에서는 REPEATABLE READ 가 기본 Isolation Level 이다.

이것이 가능한 이유는 InnoDB 가 MVCC(Multi-Version Concurrency Control) 를 사용하기 때문이다. MVCCundo log 를 사용하여 데이터에 대하여 여러 버전을 가질 수 있게 된다. 이러한 특징으로 인해 Isolation Level 에 따라 다르게 데이터를 읽을 수 있다.

REPEATABLE READ 는 undo log 의 TRX_ID(Transaction ID) 를 사용하여 데이터를 읽게 된다. 현재 트랜잭션보다 작은 TRX_ID 를 가진 데이터는 읽을 수 있지만 큰 TRX_ID 를 가진 데이터는 읽을 수 없다.

그래서 READ COMMITTED 에서 발생하는 NON-REPEATABLE READ 가 발생하지 않는다.

그러나 REPEATABLE READ 는 PHANTOM READ 가 발생할 수 있다.

PHANTOM READ 란 같은 트랜잭션에서 같은 데이터를 읽었을 때 유령(phantom) 과 같이 row 가 추가되거나 삭제되는 것을 말한다.

SELECT … FOR UPDATE 또는 SELECT … LOCK IN SHARE MODE 을 사용하면 PHANTOM READ 가 발생할 수 있다. 이유는 undo loglock 을 걸 수 없기 때문에 undo log 에서 데이터를 가져오지 못하고 최신 commit 버전 데이터를 읽게 된다.

Gap Lock 을 사용하면 PHANTOM READ 가 발생하지 않는다. Gap Lock 은 인덱스의 범위를 lock 하는 것을 말한다. 그래서 데이터 삽입을 제한할 수 있다. 예를 들어 WHERE BETWEEN 1 AND 10 을 사용하면 1 ~ 10 까지의 범위를 lock 하게 된다.

Next Key Lock 을 사용하면 PHANTOM READ 가 발생하지 않는다. Next Key Lock 은 Gap Lock 과 Record Lock 을 합친 것을 말한다. 즉 Next Key Lock 은 WHERE BETWEEN 1 AND 10 을 사용하면 1 ~ 10 까지의 범위를 lock 하고 10 까지의 record 를 lock 하게 된다.

InnoDB 엔진은 REPEATABLE READ 를 사용할 때 Gap LockNext Key Lock 을 사용해서 PHANTOM READ 가 발생하지 않도록 한다.

SERIALIZABLE

SERIALIZABLE 은 REPEATABLE READ 에서 발생하는 PHANTOM READ 가 발생하지 않는다. 그러므로 가장 격리성이 높은 Isolation Level 이다. 그만큼 성능이 떨어진다. 읽기 작업 시 lock 을 걸기 때문에 성능이 떨어진다.

InnoDB 는 순수 SELECT 를 암시적으로 SELECT … FOR SHARE 로 변경한다.

참고 자료


MySQL Global buffers, Global caches, Session buffers

목표

Global buffers, Global caches, Session buffers 에 대해 알아보자.

MySQL Index Covering

목표

MySQL 의 Index Covering 에 대해 알아보자.

NCloud LB & SourcePipeline 구축하기
tech collection 서비스 성능 개선하기
Selenium 복권 구매 자동화 만들어보기
디자인 패턴
책 리뷰
블로그 챌린지