데이터베이스

[MySQL] Transaction Isolation level

jwKim96 2022. 5. 12. 16:26

MySQL 8.0 을 기준으로 작성되었습니다.

Transaction Isolation level

Transaction Isolation level 이란 다른 Transaction 에서 접근해 데이터를 변경하거나 조회할 수 있도록 하는 수준입니다.

예를들어 현재 실행중인 Transaction_A, 그 다음 실행된 Transaction_B 가 있다고 가정하겠습니다.

Transaction_A 의 격리 수준을 높이면 Transaction_B 가 방해할 여지가 줄어들게 됩니다.
그러면 데이터의 일관성(Consistency)이 높아집니다.
하지만 Transaction_A 가 끝날때까지 Transaction_B 는 대기해야합니다.
그래서 동시성(Concurrency) 은 감소합니다.

반대로 Transaction_A 의 격리 수준을 낮추면, Transaction_B 가 방해할 여지가 생깁니다.
그러면 데이터의 일관성(Consistency) 은 낮아집니다.
하지만, Transaction_B 가 대기할 필요가 없기 때문에, 동시성(Concurrency) 은 증가합니다.

이를 그래프로 표현한 것이 아래 그래프입니다.

위 예시의 설명과 같이 Isolation leve 에 따라 변화하는 일관성(Consistency)동시성(Concurrency) 을 나타내는 그래프 입니다.

그림에서 보시다시피 Isolation level 은 4종류가 있습니다.

  • READ UNCOMMITTED
  • READ COMMITED
  • REPEATABLE READ
  • SERIALIZE

격리 수준이 낮은 순서대로 특징을 살펴보겠습니다.

READ UNCOMMITTED

  • COMMIT 되지 않은 데이터에 다른 Transaction 이 접근 가능
  • INSERT, UPDATE, DELETE 후 COMMIT 혹은 ROLLBACK 여부에 상관없이 현재 테이터를 조회함
  • ROLLBACK 이 될 예정인 데이터를 조회할 수 있어서 주의가 필요함
  • LOCK 이 발생하지 않음

위 내용을 한마디로 요약하면, 무조건 현재 가장 최신 테이터를 조회 한다고 이해할 수 있습니다.
LOCK 이 발생하지 않기 때문에, Transaction 의 대기시간을 줄일 수 있지만 무결성을 해칠 가능성이 높은 Isolaction level 입니다.
이는 dirty read* 라고도 하며, 반대 개념으로는 consistent read* 가 있습니다.

dirty read

다른 Transaction 에 의해 변경되었지만 COMMIT 되지 않은 데이터를 조회하는 작업입니다.
신뢰할 수 없는 데이터이며, READ UNCOMMITTED 격리 수준에서만 가능합니다.

consistent read(Consistent Nonlocking read)

InnoDB 가 여러 버전의 데이터베이스 스냅샷을 제공하는 읽기 방법입니다.
즉, consistent read 를 실행하면 다른 Transaction 의 COMMIT 이 반영된 최신 snapshot 을 생성하고 이를 기준으로 읽기를 실행합니다.
그러나 트랜잭션 내에서 여러번 consistent read 가 발생하면, 각자의 snapshot 을 생성하여 읽어옵니다.
그래서 이렇게 생성된 snapshot 은 실제 DB 에는 존재한적 없는 테이블 형태가 될 수 있습니다.

참고

READ COMMITTED

스냅샷을 Transaction 내에서 공유하는 REPEATABLE READ 와는 다르게 동일한 Transaction 내에서도 각 일관된 읽기(consistent read) 쿼리는 자체 스냅샷을 생성하여 읽습니다.

READ COMMITTED 는 아래와 같은 특징이 있습니다.

  • Locking read*, UPDATE, DELETE 쿼리 실행시 locking 이 발생함
    해당하는 index record 에 대해 record lock 이 발생합니다.
    gap lock 이 발생하지 않기 때문에, ... WHERE c1 BETWEEN 10 and 20 FOR UPDATE
    같은 locking read 쿼리가 발생하더라도 다른 트랜잭션이 c1 컬럼에 대해 15번을 입력하거나
    수정하는것이 가능합니다.
  • MySQL에서 많은 양의 데이터를 복제하거나 이동할 때 이 LEVEL을 추천함

locking read

  • SELECT ... FOR UPDATE
    다른 트랜잭션에서 데이터를 변경 하려는 행위를 기다리게합니다.
  • SELECT ... FOR SHARE or SELECT ... LOCK IN SHARE MODE
    다른 트랜잭션에서 데이터를 읽거나 변경하려는 행위를 기다리게합니다.
    기존에는 LOCK IN SHARE MODE 가 사용되었으나 8.0 부터는 FOR SHARE 키워드로 대체되었습니다.
    하지만 호환성을 위해 두 키워드 모두 사용 가능합니다.

참고 : MySQL 8.0 locking read

REPEATABLE READ

REPEATABLE READ 는 InnoDB 의 기본 Isolation level 로 설정되어있으며, 다음과 같은 특징이 있습니다.

  • Transaction 내에서 처음 조회한 데이터로 스냅샷을 생성함
    이후 조회시에는 생성된 스냅샷을 조회함
  • 동일 트랜잭션 내에서 일관성 보장
  • Locking read, UPDATE, DELETE 쿼리 실행시 locking 이 발생함
    unique index 로 특정 데이터를 검색하는지, 범위를 검색하는지에 따라 해당 index record 들에 대해 record lock 혹은 gap lock* 이 발생합니다.
    • 특정 데이터 검색 : record lock 이 발생함
    • 범위 검색 : gap lock* 이 발생함

gap lock

Index record 들의 범위를 lock 함.

예를들어 SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; 쿼리를 실행하면
10~20 인덱스가 lock 상태가 됩니다.
만약 여기서 다른 트랜잭션이 c1 컬럼에 대해 15번을 입력하거나 수정하는것이 불가합니다.
즉, 15번이 존재하는지와는 관계없이 10~20 범위는 무조건 lock 상태가 됩니다.

  • 입력 예 : INSERT INTO t (c1) VALUES (15);
  • 수정 예 : UPDATE t SET c1=15 WHERE id=15;

참고 : MySQL 8.0 gap lock

SERIALIZE

SERIALIZE 격리 수준은 REPEATABLE READ 와 비슷하지만 auto commit 설정 여부에 따라 다르게 동작합니다.

  • auto commit 비활성화
    암묵적으로 모든 SELECTSELECT ... FOR SHARE 로 변환합니다.
  • auto commit 활성화
    모든 SELECT 가 자체 Transaction 을 가집니다.
    이런 동작방식은 read only 로 알려져있습니다.
    그리고 다른 Transaction 에 의해 차단되지 않은 consistent read 라면,
  • 주로 XA Transaction* 이 사용되는 환경에서 동시성과 교착상태 문제를 해결하는데 주로 쓰입니다.

XA Transaction

분산환경에서의 트랜잭션을 위한 표준 인터페이스입니다.
ACID complience* 를 유지하며 여러 데이터베이스가 하나의 Transaction 에 참여할 수 있습니다.

ACID complience

Database Transaction 이 적시에 완료되는것을 보장하기 위한 4가지 특성을 말합니다.

  • Atomicity : 원자성
  • Consistency : 일관성
  • Isolation : 격리성
  • Durability : 내구성(장애 복구)

참고