Isolation

Tony·2023년 5월 14일

Database

목록 보기
1/2

Intro

DBMS에서는 보통 여러 개의 transaction이 동시에 진행됩니다. 이때, 복수의 transaction에서 같은 자원에 접근하는 경우가 있습니다. 자원의 읽기(Read)만 수행된다면, 원본(Original Copy)이 변형되지 않으므로 항상 같은 값을 반환하면 됩니다. 하지만, 문제는 자원의 쓰기(Write)에서 발생합니다. 하나의 DBMS 자원에 대해 여러 개의 쓰기와 읽기가 수행된다고 가정한다면, 어떤 쓰기를 먼저 반영할지, 쓰기 연산들 사이에 일어난 읽기에 대해서는 어떠한 값을 반환해야할지 정해야합니다.
이렇게 DBMS의 자원에 대한 race condition을 원만하게 해결하기 위한 방법이 DBMS isolation입니다. Isolation은 고립이라는 의미를 나타냅니다. DBMS에서 얽히고 설킨 transaction들 사이에서 다른 transaction들 사이에서 하나의 transaction을 고립시키는 것에 대한 것이 DBMS isolation입니다.
Transaction들 사이의 동시성 문제를 정말로 어렵게 만드는 것은, transaction은 단발성 이벤트가 아니라 시작과 끝이 있는 연속성 이벤트라는 점입니다. 그러므로, Transaction 내에서 쓰기가 발생해서 자원을 변형시키더라도, 커밋(Commit)이전에 문제가 발생하면 자원을 쓰기 이전 값으로 되돌립니다(Rollback). 이러한 메커니즘이 isolation을 힘들게 하지만, 이또한 transaction의 atomicity를 보장하기 위한 메커니즘이므로 꼭 필요한 부분입니다.

Troubling Points

선배 컴퓨터 과학자님들은 transaction들이 고립되지 않았을때 어떠한 문제가 발생할 수 있는지 연구했습니다. 그리고 아래 3가지 문제가 발생할 수 있음을 남겼습니다.
아래 문제들은 복수의 transaction가 동시에 진행 중일때 발생하는 문제들입니다. 따라서 동시에 진행 중인 transaction 1번과 2번이 있다고 가정하고 설명하겠습니다. 이 문제들은 Data anormaly 라고 부르고, 말그대로 데이터 이상현상을 뜻합니다.

1. Dirty Read

transaction 1번이 어떠한 자원에 대해 쓰기 연산을 하고 아직 커밋하지 않은 값을 transaction 2번이 읽었습니다. 그런데, transaction 1번이 롤백 되었습니다.
이때, 자원은 롤백되어 이전 값을 지니지만, transaction 2번을 수행했던 어플리케이션은 롤백되기 이전의 값을 읽고 해당 값을 이용해 로직을 수행 중일 것입니다.
이러한 읽기(Read) 상황을 Dirty Read라고 합니다. 커밋이 되어 견고하고 깔끔한 상태에 있는 자원을 읽은 것이 아니라, 롤백할 수도 있는 불안정한 상태의 자원을 읽었다고 하여 Dirty Read라고 부르는 것 같습니다.

2. Non Repeatable Read

transaction 1번이 어떠한 자원에 대해 값을 읽었습니다. 바로 직후에, transaction 2번에 해당 자원을 쓰기 연산을 통해 변형시키고 커밋했습니다. 그리고 얼마 후, transaction 1번이 다시 해당 자원을 읽었습니다.
이때, transaction 1번이 읽은 자원의 값은 처음 읽었던 값과 다를 것입니다. 이러한 읽기 상황을 Non Repeatable Read라고 합니다.
이전 값이 변형되었으므로, 다시 읽었을 때 이전의 값을 읽어올 수 없다는 의미로 Non-repeatable라고 부르는 것 같습니다.

3. Phantom Read

Phantom Read는 자원의 추가/제거로 인해 발생할 수 있는 문제입니다.
Transaction 1이 이떠한 쿼리조건을 만족하는 모든 자원에 대해 읽기 연산을 했습니다. 이때 3개가 반환되었다고 가정해봅시다.
Transaction 2에서 자원을 몇개 더 추가하고 커밋했습니다. 그런데, 그 중에 우연히 transaction 1이 수행했던 쿼리조건에 해당하는 자원이 포함되어 있었습니다.
이 상황에서 Transaction 1이 처음 읽기 쿼리를 한번더 수행하면, 반환되는 자원은 3개가 됩니다.
Transaction 1의 입장에서는 가만히 있었는데 같은 쿼리 조건에 해당하는 자원의 수가 늘었습니다. Transaction 1을 수행한 클라이언트는 아마 유령을 본 듯한 느낌이 들 것 같습니다.
이 상황을 Phantom Read라고 합니다.

Isolation Level

Isolation Level을 나누는 기준은 여러가지로 생각할 수 있을 것 같습니다.
위의 문제들을 얼마나 해결하느냐에 따라 나눌 수도 있을 것이고, transaction들을 얼마나 서로 고립시키느냐에 따라 나눌 수도 있을 것입니다. 중요한 포인트는, 모두 같은 맥락에 있다는 점입니다. 위의 문제들을 해결할수록 transaction은 더욱 고립됩니다.
각 isolation level에 공부하기 전에 알아둬야할 것은, isolation의 정도가 커질수록 DBMS의 성능이 떨어진다는 것입니다. 즉, trade-off 관계에 있습니다. 따라서 isolation의 정도가 클수록 좋은 것이 아닙니다. 반대로, isolation를 하지 않는다면 transaction들의 동시성이 최대화 되어 성능은 좋겠지만 자원의 일관성이 전혀 보장되지 않아 클라이언트가 이용하기에는 무리가 있을 것입니다.
Isolation level을 나누어둔 이유는, 개발자가 적절하게 상황에 맞는 isolation 정도를 선택하여 개발할 수 있도록 하기 위함입니다. 아래에는 isolation level이 isolation 정도를 기준으로 오름차순으로 나열되어 있습니다.

Read Uncommitted

다른 transaction이 아직 커밋하지 않은 값을 읽을 수 있을 정도의 고립 정도입니다. 사실상 고립이 없는 상태를 의미합니다. 그러므로, 위에 언급한 3가지 문제가 전부 다 나타날 수 있는 isolation level입니다.

Read Committed

한 transaction이 자원에 쓰기연산을 수행하고 커밋한 이후에, 다른 tranasction 해당 변화를 읽을 수 있는 고립 정도입니다. 그러므로, Dirty Read는 발생하지 않습니다.

Repeatable Read

한 transaction이 시작하면, 해당 transaction에서 일어난 읽기연산은 다른 transaction에서 일으킨 변화에 영향받지 않습니다.
예를 들어, 동시에 시작한 transaction 1번, 2번이 있다고 가정해봅시다. 그리고 두 transcation이 시작하기 전에 어떤 자원의 값이 4였습니다.
Transaction 2번이 이 자원의 값을 5로 바꿨습니다. 그리고, transaction 1번이 이 자원을 읽었습니다. 이때, transaction 1번이 읽은 값은 4입니다.
Repeatable Read에서는, 한 transaction이 다른 transaction의 쓰기연산에 영향을 받지 않으므로 Dirty Read, Non Repeatable Read가 발생할 수 없습니다.

Serializable

Transaction을 한번에 1개만 수행되도록 하는 isolation level입니다. 따라서, 시간축을 따라 각 transaction의 수행시간을 그리면 아래와 같이 서로 겹치지 않고 일렬로 정렬됩니다.

Transaction이 완전 고립된 상태이기 때문에, 위에서 언급한 3가지 문제는 발생하지 않습니다.

0개의 댓글