트랜잭션 격리 수준 알아보기

박진형·2022년 6월 9일
0

트랜잭션이란?

트랜잭션이란 더 이상 쪼갤 수 없는 업무 처리의 최소 단위이다.
데이터베이스에서는 DB 데이터 변경 시 변경 내용들을 하나의 작업단위로 묶고 이 단위를 트랜잭션이라고 부른다.

트랜잭션의 특징

원자성

트랜잭션이 하나의 작업 단위라고 앞서 언급했다. 그렇다면 작업 도중 오류가 발생한다면? 작업을 취소 하고자 한다면?
트랜잭션 단위별로 Rollback을 한다. 반면 문제 없이 변경이 수행된다면? 모두 Commit된다.
즉,트랜잭션은 DB에 모두 반영되거나, 전혀 반영되지 않아야한다.

일관성

트랜잭션의 작업 처리 결과가 항상 일관성 있어야한다.
트랜잭션이 진행되는 동안 데이터베이스의 상태가 변경되어도 트랜잭션이 시작된 시점의 데이터 베이스 상태를 기반으로 작업이 진행된다.

독립성

둘 이상의 트랜잭션이 동시에 수행될 때, 어떠한 트랜잭션이 다른 트랜잭션의 연산에 끼어들 수 없는 성질이다.
여기에도 얼마나 엄격하게 제한하냐에 따라 격리수준이 4가지로 나뉘어진다. 이것에 대해서 오늘 자세하게 알아볼 예정이다.

지속성

트랜잭션이 성공적으로 완료되었다면, 결과는 영구적으로 반영되어야한다.

트랜잭션 격리 수준

트랜잭션 격리 수준이란 독립성이 얼마나 엄격하게 보장되느냐를 단계별로 나눈 것이다.

격리 수준은 크게 격리 레벨이 가장 낮은 수준 부터 아래 4단계로 나뉜다.

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE

DIRTY READ

A트랜잭션에서의 변경사항을 커밋하기 전에 B트랜잭션이 조회하는 경우를 뜻한다.

PHANTOM READ

A 트랜잭션에서의 첫번째 쿼리 결과에는 없었던 데이터가 동시에 수행되는 B 트랜잭션에서 삽입된 데이터로 인해 A트랜잭션의 두번째 쿼리 결과에는 나타나는 현상을 뜻한다.

NON-REPEATABLE READ

A 트랜잭션에서 처음 쿼리한 행이 나중의 쿼리 결과가 동시에 수행되는 B 트랜잭션 때문에 달라지는 현상이다.

PHANTOM READ VS NON-REPEATABLE READ
PHANTOM READ는 삽입이나 삭제에 의해 쿼리 집합의 결과 개수가 달라지는 것이고 NON REPEATABLE READ는 처음 검색한 행의 컬럼 값들이 UPDATE되어 두번째 검색했을 때 달라지는 경우를 뜻하는 것 같다.
쉽게 말해서 테이블의 관점에서는 PHANTOM READ, 행의 관점에서는 NON-REPEATABLE READ가 발생한다.
https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_phantom

Read UnCommitted

어떤 트랜잭션의 변경내용이 COMMIT되지 않아도 다른 트랜잭션에서 보여지는 경우다.
1. 닭장에는 병아리가 한마리 있다.
2. B 트랜잭션에서 닭장을 조회한다. (병아리 1)
3. A 트랜잭션에서 닭장에 닭을 추가한다.
4. B 트랜잭션에서 닭장을 조회한다. (병아리 1, 닭 1)
5. A 트랜잭션에서 ROLLBACK한다.
6. B 트랜잭션에서 닭장을 조회한다.(병아리 1)

Read Committed

어떤 트랜잭션의 변경내용이 COMMIT되어야지만 다른 트랜잭션에서 보일 수 있다.

  1. 닭장에는 병아리가 한마리 있다.
  2. B 트랜잭션에서 닭장을 조회한다. (병아리 1)
  3. A 트랜잭션에서 병아리를 닭으로 바꾼다.
  4. B 트랜잭션에서 닭장을 조회한다. (COMMIT 되기 전이므로 병아리1)
  5. A 트랜잭션에서 COMMIT한다.
  6. B 트랜잭션에서 닭장을 조회한다.(닭 1)

같은 닭장을 조회했지만 2번 결과와 6번결과가 다르다. NON-REPEATABLE READ 현상이 발생했다.

DIRTY READ는 발생하지 않지만 여전히 PHANTOM READ나 NON-REPEATABLE READ가 발생할 수 있다.

Repeatable Read

어떤 트랜잭션의 변경내용이 COMMIT 되어도 다른 트랜잭션에서는 그 트랜잭션의 시작 시점의 데이터만 보여준다.(Consistent read)
MySQL InnoDB엔진에서 사용하는 디폴트 레벨이다.

  1. 닭장에는 병아리가 한마리 있다.
  2. B 트랜잭션에서 닭장을 조회한다. (병아리 1)
  3. A 트랜잭션에서 병아리를 닭으로 바꾼다.
  4. B 트랜잭션에서 닭장을 조회한다. (COMMIT 되기 전이므로 병아리1)
  5. A 트랜잭션에서 COMMIT한다.
  6. B 트랜잭션에서 닭장을 조회한다.(병아리 1)

NON-REPEATABLE READ가 발생하진 않지만 PHANTOM READ가 발생할 수 있다.

MySQL에서는 REPEATABLE READ 레벨에서도 PHANTOM READ가 발생하지 않는다.

Serializable

트랜잭션이 완료될 때 까지 SELECT 문장이 사용되는 모든 데이터에 Shared Lock이 걸린다.

트랜잭션이 특정 테이블을 읽으면 다른 트랜잭션은 해당 테이블에 대해 추가/변경/삭제를 할 수 없다.
가장 강력한 격리 수준으로 정합성을 잘 보장하지만 동시 처리 성능이 떨어진다.

MVCC(Multi-Version Concurrency Control)

동시 접근을 허용하는 데이터베이스에서 동시성을 제어하기 위해 사용하는 방법 기존의 Lock 방식은 읽기/쓰기 작업을 방해하기 때문에 성능에 문제가 발생한다.
데이터를 변경할 때 변경사항을 Undo 영역에 저장해두고 다루며 원본 데이터에 영향을 끼치지 않도록 하는 기법이다.

  • 얼핏보면 Lock보다 좋아보이지만 여러가지 오버헤드는 무시하지 못한다.(Undo 블록 I/O, CR Copy 생성, CR 블록 캐싱)
  • Snapshot too old 문제가 발생할 수 있다.

결론

  • 트랜잭션 격리수준은 4가지로 나뉘고 다음 표와 같이 수준에 따라 정합성 문제가 발생할 수 있다.

    격리수준Dirty ReadNon-Repeatable ReadPhantom Read
    Read UncommittedOOO
    Read CommittedXOO
    Repeatable ReadXXO
    SerializableXXX
  • MySQL은 Repeatable Read 레벨을 기본으로 사용하고 표준과는 달리 Repeatable 단계에서도 Phantom Read가 발생하지 않는다.(MVCC)

  • 많은 DB들이 MVCC기법을 Lock과 더불어 채택하고 있다. 장단점이 있다.

0개의 댓글