언어/SQL

[SQL] 트랜잭션의 격리 수준(isolation Level)

개발자들아제발자 2022. 12. 3. 23:33

트랜잭션의 격리 수준(isolation)이란?

트랜잭션의 격리 수준(Isolation level)이란 동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를  볼 수 있도록 허용할지 말지를 결정하는 것이다.

 

트랜잭션의 격리 수준 종류

  • READ UNCOMMITTED(커밋되지 않은 읽기)
  • READ COMMITTED(커밋된 읽기)
  • REPEATABLE READ(반복 가능한 읽기)
  • SERIALIZABLE(직렬화 가능)
격리수준 DIRTY READ NON-REPEATABLE-READ PHANTOM-READ
READ UNCOMMITTED O O O
READ COMMITED   O O
REPEATABLE READ     O(InnoDB는 발생 X)
SERIALIZABLE      

1. READ UNCOMMITTED

READ UNCOMMITTED 격리 수준에서는 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 보여지게 된다.

 

이처럼 어떠한 트랜잭션에서 처리한 작업이 완료되지 않았음에도 불구하고 다른 트랜잭션에서 볼 수 있는 현상더티 리드(Dirty Read)라 하고, 더티 리드가 허용되는 격리 수준이 READ UNCOMMITTED이다.

더티 리드 현상은 데이터가 나타났다가 사라졌다 하는 현상을 초래하기 때문에 혼란을 발생시킨다.

 

2. READ COMMITED

READ COMMITTED 격리 수준에서는 어떠한 트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다. 이 레벨에서는 더티 리드(Dirty Read)와 같은 현상이 발생하지 않고, 오라클 DBMS에서 기본적으로 사용되고 있으며, 온라인 서비스에서 가장 많이 선택되는 격리 수준이다.

 

  • Undo 

언두 영역은 UPDATE 문장이나 DELETE와 같은 문장으로 데이터를 변경했을 때 변경되기 전의(이전 데이터)를 보관하는 곳이다.

언두의 데이터는 크게 두 가지 용도로 사용된다.

1. 트랜잭션의 롤백 대비용

2. 트랜잭션의 격리 수준을 유지하면서 높은 동시성을 제공

 

READ COMMITTED 격리 수준에서도 NON-REPEATABLE READ라는 부정합 문제가 존재한다.

사용자가 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 REPEATABLE READ 정합성에 어긋나게 된다.

가장 큰 예시로, 트랜잭션에서 동일한 데이터를 여러 번 읽고 변경하는 작업이 금전적인 처리와 연결되면 문제가 될 수 있다.

한 트랜잭션에서 입금과 출금 처리가 계속 진행중이면, 다른 트랜잭션에서 오늘 입금된 금액의 총합을 조회할 때 REPEATABLE READ가 보장되지 않기 때문에 총합을 계산하는 SELECT 쿼리를 실행할 때마다 다른 결과값을 가져오게 된다.

 

3. REPEATABLE READ

REPEATABLE READ 격리 수준에서는 어떠한 트랜잭션에서 데이터를 변경하더라도 ROLLBACK될 가능성에 대비해 변경되기 전 레코드를 언두(Undo) 영역에 백업해두고 실제 레코드 값을 변경한다. 이러한 방식을 MVCC(Multi Version Concurrency Control)이라 한다. MySQL의 InnoDB 스토리지 엔진에서 기본적으로 사용되는 격리 수준이다.

MVCC(Multi Version Concurrency Control) - 잠금을 사용하지 않는 일관된 읽기를 제공
MVCC는 다중 버전 병행수행 제어의 약자로 DBMS에서는 쓰기(Write) 세션이 읽기(Read)세션을 블로킹하지 않고, 읽기 세션이 쓰기 세션을 블로킹하지 않게 서로 다른 세션이 동일한 데이터에 접근했을 때 각 세션마다 스냅샷 이미지를 보장해주는 메커니즘이다.

모든 InnoDB의 트랜잭션은 고유한 트랜잭션 번호(순차적으로 증가)를 가지며, 언두 영역에 백업된 모든 레코드에는 변경을 발생시킨 트랜잭션의 번호가 포함되어 있다. REPEATABLE READ 격리 수준에서는 MVCC를 보장하기 위해 실행중인 트랜잭션 가운데 가장 오래된 트랜잭션 번호보다 트랜잭션 번호가 앞선 언두 영역의 데이터는 삭제할 수 없다.

 

4. SERIALIZABLE

SERIALIZABLE 격리 수준은 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서 절대 접근할 수 없다. 읽기 작업도 공유 잠금(읽기 잠금)을 획득하며, 동시에 다른 트랜잭션은 그러한 레코드를 변경할 수 없다.

SERIALIZABLE은 가장 엄격한 격리 수준으로 처리 성능이 다른 트랜잭션 격리 수준보다 현저히 떨어진다.

 

 

 

 

트랜잭션 격리 수준

  • READ UNCOMMITTED: 트랜잭션내에서 커밋하지 않은 데이터에 다른 트랜잭션의 접근이 가능
  • READ COMMITTED: 트랜잭션내에서 커밋된 데이터만 다른 트랜잭션이 읽는 것을 허용
  • REPEATABLE READ: 트랜잭션 내에서 한 번 조회한 데이터를 반복해서 조회해도 결과는 동일
  • SERIALIZABLE: 가장 엄격한 격리 수준으로 완벽한 읽기 일관성 모드 제공

격리 수준에 따라 발생할 수 있는 문제점

  • DIRTY READ: 어떠한 트랜잭션에서 처리한 작업이 롼료되지 않았음에도 불구하고 다른 트랜잭션에서 볼 수 있게 되는 현상
  • NON-REPEATABLE READ: 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 REAPEATABLE READ 정합성에 어긋나는 현상
  • PHANTOM READ: 한 트랜잭션내에서 동일한 쿼리를 두 번 수행했는데, 첫 번째 쿼리에서 존재하지 않던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상