본문 바로가기

데이터베이스

DB 트랜잭션(Transaction)과 트랜잭션 격리 수준(Isolation Level)

[트랜잭션]

여러 읽기/쓰기를 논리적으로 하나로 묶음으로

하나의 트랜잭션 내에서 여러 쿼리의 결과를 모두 커밋되거나 모두 롤백이 된다.

트랜잭션 범위는 커넥션을 기준으로 따라간다.

[트랜잭션 특징]

Atomicity(원자성)

트랜잭션은 DB에 모두 반영되거나 전혀 반영되지 않아야 한다. (all or nothing)

Consistency(일관성)

트랜잭션 작업 처리결과는 항상 일관성 있어야 한다.

Isolation(독립성)

둘 이상의 트랜잭션이 동시 실행되고 있을 때, 어떤 트랜잭션도 다른 트랜잭션 연산에 끼어들 수 없다.

Durability(지속성)

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

 

[트랜잭션의 격리 수준(Transaction Isolation Level)]

트랜잭션을 서로 격리해서 다른 트랜잭션이 영향을 주지 못하게 한다.

[격리 수준(Isolation Level] 종류]

READ UNCOMMITTED

커밋 전의 트랜잭션의 데이터 변경 내용을 다른 트랜잭션이 읽는 것을 허용한다.

SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리지 않는 계층이다.

사실상 거의 사용하지 않는다.

데이터베이스나 페이지, 열 등에 잠금을 유지하는 데 드는 간접 비용이 제일 적다.

교착 상태에 빠질 위험이 적어 성능이 빠르고 우수하다.

주의

  • 데이터 정합성에 문제가 많으므로, 되도록이면 사용하지 않는 것이 이상적이다.
  • 트랜잭션 도중에 값을 얻어낼 수 있으므로, 복잡한 stored procedure나 함수가 포함된 디버깅을 할 때 중간 과정을 확인하기 위해 사용하는 경우도 존재한다.
  • 발생가능한 문제점으로 Dirty Read, Non-Repeatable Read, Phantom Read가 있다.

 

READ COMMITTED

커밋이 완료된 트랜잭션의 변경사항만 다른 트랜잭션에서 조회 가능하다.

커밋 전에는 실제 테에블의 값이 아닌 Undo 영역에 백업된 변경 전 데이터를 읽고 커밋 후에는 변경 후 데이터를 읽는다.

SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리는 계층이다.

커밋된 결과만 읽어오므로 Dirty Read가 발생하지 않는다.

대부분의 SQL 서버가 Default로 사용하는 Isolation Level이다.(e.g. Oracle)

주의

  • 잠금이 발생하므로 속도나 성능에 있어서 느릴 수 있다.
  • 트랜잭션 간 고립성을 완전히 보장하지 못한다.
    → 각 트랜잭션의 정확도를 생명으로 하는 웹 애플리케이션 구동에는 적합하지 않다.
    e.g.) 은행 계좌 정보 조회
  • 발생가능한 문제점으로 Non-Repeatable Read, Phantom Read가 있다.

REPEATABLE READ

트랜잭션 동안 조회한 데이터 내용이 항상 동일함을 보장한다.

(자신의 트랜잭션 번호보다 먼저 발생한 트랜잭션 번호에서 커밋된 것만 볼 수 있다.)

  • 모든 InnoDB의 트랜잭션은 순차적으로 증가하는 고유한 트랜잭션 번호를 갖는다
  • Undo 영역에 백업된 모든 레코드는 변경을 발생시킨 트랜잭션의 번호를 포함한다.

커밋된 데이터만 읽을 수 있도록 커밋된 값과 트랜잭션 진행 중인 값을 Undo 영역에 보관한다.

진행 중인 데이터는 읽지 않도록 커밋된 데이터만 덮어쓰기는데 이것은 행 단위로 잠금을 사용하여 같은 데이터를 수정한 트랜잭션이 끝날 때까지 대기하도록 한다.

트랜잭션이 범위 내에서 조회한 데이터 내용이 항상 동일함을 보장한다.

MySQL에서 Default로 사용하는 Isolation Level이다.

주의

  • 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정이 불가능하다.
  • 잠금이 적용되는 범위가 넓어져 성능과 속도가 느려진다.
  • Phantom Read 발생 가능성 존재한다.
    → MySQL의 InnoDB는 멀티 버전 동시성 제어를 통해 어느정도 극복(next key lock 이용)

 

SERIALIZABLE

가장 단순하면서도 엄격한 격리수준이다.

가장 격리 수준이 높으며 한 트랜잭션에서 특정 테이블을 조회할 경우, 다른 트랜잭션에서 데이터에 대한 수정 및 입력 불가능하다. → 동시처리 능력이 다른 격리수준보다 떨어지며, 성능저하 발생한다.

트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리는 계층이다.
완벽한 읽기 일관성 모드를 제공한다.

모든 것이 순차적으로 진행되므로 Phantom Read가 발생하지 않는다.

데이터베이스에서 거의 사용되지 않는다.

 

[격리 수준별 발생하는 문제들]

  Dirty Read Non-Repeatable Phatom Read
READ UNCOMMITED O O O
READ COMMITED X O O
REPEATABLE READ X X O
SERIALIZABLE X X X

Dirty Read

커밋되지 않은 변경된 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생하는 문제이다.

Transaction A가 데이터에 접근하여 값을 'A에서 'B'로 변경 후 아직 커밋하지 않은 상태에서, Transaction B가 해당 데이터를 read를 하게되면 'B'를 읽게된다.

여기서 Transaction A가 최종 Commit을 하지 않고 종료하게되면, Transactin B가 갖고 있는 데이터가 꼬이게 된다.

 

Non-Repeatable

한 트랜잭션에서 같은 쿼리를 두 번 수행할 때 그 사이에 다른 트랜잭션 값을 수정 또는 삭제하면서 두 쿼리의 결과가 상이하게 나타나는 일관성이 깨지며 발생한 문제이다.

Transaction A가 데이터에 접근하여 값을 'A에서 'B'로 변경 후 아직 커밋하지 않은 상태에서, Transaction B가 해당 데이터를 read하게되면 'A'를 읽게된다.
Transaction A가 커밋을 한 뒤에 다시 Transaction B가 해당 데이터를 read하면 'B' 를 조회한다.

 

Phatom Read

Non-Repeatable의 하나의 종류로 한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽었을 때, 첫 번째 쿼리에서 없던 레코드가 두 번째 쿼리에서 나타나는 문제이다.

트랜잭션 도중 새로운 레코드 삽입을 허용하기 때문에 발생한다.

Transaction A중에 특정 조건으로 데이터를 검색하고 결과를 얻은 다음 Transaction B가 접근하여 데이터를 삭제/추가하면, 종료되지 않은 Transaction B에서 추가/삭제된 데이터가 함께 조회/누락 되는 것이다.

이후 Transaction B가 롤백을 하면 데이터가 꼬이게된다.

 

 

Reference.
[DB] 트랜잭션 격리 수준
https://www.youtube.com/watch?v=urpF7jwVNWs
https://www.youtube.com/watch?v=poyjLx-LOEU&t=1053s
https://www.youtube.com/watch?v=aX9c7z9l_u8

 

'데이터베이스' 카테고리의 다른 글

[DB]인덱스와 인덱스의 장단점  (0) 2022.09.08
INNER JOIN과 OUTER JOIN  (0) 2022.08.29