[DB] Transaction Isolation Level이란?

chrisjune
4 min readSep 14, 2019

데이터베이스의 기초개념인 트랜젝션 격리수준에 대해 알아봅니다.

DBMS에서는 여러 사용자가 동일한 데이터를 동시에 수정하려고 할 때, 발생하는 상황을 정확하게 정의할 수 있도록 여러 기능을 제공합니다. 그중 하나가 바로 Isolation level(이하, 격리수준)이라고 합니다.

데이터 무결성을 유지시키고 성능을 높이기 위해서 꼭 알아야하지만, 직관적으로 이해하기 어렵습니다. 따라서 아래에서는 용어보다는 예를 통하여 알아보도록 하겠습니다.

먼저, 격리수준은 아래와 같이 세개의 수준을 가지고 있으며, 대부분의 데이터베이스에서는 1단계인 Read Committed가 기본 수준입니다.

Isolation Level

  • 1단계, Read Committed
  • 2단계, Repeatable Read
  • 3단계, Serializable

모든 트랜젝션은 이 중 하나의 격리수준중 하나를 설정합니다. 대부분의 DBMS에서 Read Committed를 기본으로 설정합니다. SQL 표준에서는 Read Uncommitted가 존재하긴 하지만 잘 사용하지 않고, Postgresql에서는 지원하지 않기 때문에 제외하여 설명하도록 하겠습니다.

Read Committed

이름처럼 커밋된 데이터만 읽는 격리 수준입니다.

A 트랜젝션에서 데이터를 생성하고 커밋하지 않은 상태에서, B 트랜젝션에서 해당테이블의 데이터를 읽으려고 하면 어떻게 될까요?

커밋하지 않은 데이터를 읽을 수 있다면, 이를 Dirty read라고 부릅니다. Read Committed에서는 Dirty read가 발생하지 않도록 보장해줍니다.

Read Committed

두번째 트랜젝션에서는 첫번째 트랜젝션에서 커밋되지 않은 데이터를 읽을 수 없습니다. Postgresql에서는 이보다 낮은 Read Uncommitted 격리수준을 지원하지 않기 때문에 Dirty read가 불가능합니다.

Repeatable Read

데이터 조회시 항상 동일한 데이터 응답을 보장하는 고립수준입니다.

Read Committed의 문제는 하나의 Row를 조회후 다시 조회했을 때, 데이터가 동일하다는 보장을 해주지 않습니다. 그 이유는 다른 트랜젝션에서 해당 데이터가 갱신되었기 때문입니다. 이를 Non-repeatable read 라고도 합니다

Non-repeatable read

이러한 문제점을 해결하려면 Repeatable Read 고립수준으로 설정하면됩니다. 그러면, 언제 조회하여도 처음과와 동일한 결과를 받게 됩니다.

Repeatable Read

여기서는 Transaction의 변경을 Begin 명령어와 같이 사용하였습니다. 이렇게 하면 컨넥션이 유지되는 동안에만 해당 격리수준으로 변경시켜줍니다. 격리수준의 변경은 공식문서를 참고하세요

Serializable

Serializable은 모든 작업을 하나의 트랜젝션에서 처리하는 것과 같은 높은 고립수준을 제공합니다. 고립수준이 높은 만큼, 동시성 처리효율은 떨어집니다.

위의 두 고립수준에서 남은 이슈는, 하나의 트랜젝션에서 자신이 조회한 자료 세트 범위가 다른 세션에 의해서 변경되는 경우 입니다. 예를 들어 가지고 있는 옷의 개수가 처음엔 100개였는데, 다시 조회시 대상이 줄어들거나 늘어나는 경우입니다. 다른 세션에서 insert하거나 delete를 해서 자신의 세션에서 조회한 자료 세트가 변경 되는 경우 자신이 조작하지 않았는데, 유령처럼 바뀐다고 하여 이를 Phantom Read 라고도 합니다.

다만, Postgresql에서는 이 Repeatable read 격리수준에서는 Phantom read 현상을 볼 수가 없고, read committed 수준에서 발생합니다.

만약 이런 현상이 발생하지 않아야 한다면, 격리수준을 Serializable로 변경하면 됩니다. 예제에서

Serializable

이 수준에서는, 두번째 트랜젝션의 갱신작업이 실패합니다. 첫번째 트랜젝션으로 인하여 데이터의 기준이 달라졌기 때문에 두번째 트렌젝션이 수행되려고 할때 실패하고 Could not serialize access due to concurrent update라는 에러가 발생하게 됩니다.

Serialization은 가장 높은 격리 수준을 제공합니다. 따라서 작업이 실패한 경우, Skip 또는 재시도등의 사후 처리를 Application에서 확인후 처리해주어야 합니다.

참고링크

--

--