본문 바로가기
DB

데이터베이스 - 트랜잭션의 격리수준

by 준벨롭 2024. 4. 7.

트랜잭션이란?

데이터베이스에서 하나의 논리적 기능을 수행하기 위한 작업의 단위를 말한다.

데이터베이스에 접근하는 방법은 쿼리이므로, 여러개의 쿼리들을 하나로 묶는 단위를 말한다.

 

트랜잭션은 'ACID' 특징이 있는데, 이는 각각 원자성, 일관성, 독립성, 지속성이 있는데

 

이 중에서 I인 Isolation 격리성에 대해 공부했다.

 

격리 수준은 4가지로 구분되는데, 

1. read_uncommited

2. read_commited

3. repeatable_read

4. serializable

 

순위가 높을수록, 동시성은 높지만 격리성은 떨어진다.

즉, serializable은 격리성이 높은대신 동시성이 떨어진다는 것을 의미한다.

 

1. read_uncommited

가장 낮은 격리 수준으로, 트랜잭션이 커밋되기 전에 다른 트랜잭션에서 접근이 가능하다는 문제가 있지만 가장 빠르다.

데이터 무결성을 위해 사용하지 않는것을 권장하나, 일부 행이 조회되지 않더라도 많은 양의 데이터를 어림잡아서 집계할 때는 효과적이다.

 

2. read_uncommited

가장 많이 사용되는 격리 수준이다. read_uncommited와는 다르게 커밋되지 않은 정보는 읽을 수 없다. 따라서 커밋이 된 데이터에만 접근이 가능하다. 하지만 어떤 트랜잭션이 접근한 행을 다른 트랜잭션이 수정할 수도 있다.

그래서 먼저 실행된 트랜잭션이 다싯 정보를 읽을 때 다른 내용을 조회하는 현상이 발생할 수 있다.

 

3. repeatable_read

하나의 트랜잭션이 수정한 행을 다른 트랜잭션이 수정할 수 없도록 막아주지만, 새로운 행을 추가하는 것은 막지 않는다.

따라서 다시 조회했을때 새로운 행이 발견될 수 있다. MySQL8.0의 innoDB 기본값이다.

 

4. serializable

트랜잭션을 순차적으로 진행시키는 것을 말한다. 여러 트랜잭션이 동시에 접근할 수 없다.

매우 엄격한 수준으로 해당 행에 대해 격리시키고, 트랜잭션이 이 행에 대해 일어난다면 기다려야 한다.

그렇게 때문에 교착 상태가 일어날 확률이 가장 높고, 성능이 매우 떨어지는 격리수준이다.

 

각 수준에서 발생하는 현상들이 존재하는데 다음과 같다.

1. phantom read

2. non-repeatable read

3. dirty read

 

1. phantom read

repeatable_read, read_commited, read_uncommited에서 발생할 수 있다.

한 트랜잭션 내에서 동일한 쿼리를 보냈을 때 해당 조회결과가 다른 경우를 말한다.

격리수준 3번인 repeatable_read에서 말했던 것과 같이, 새로운 행을 추가하게 된다면 다시 조회했을 때 이전과는 다른 값이 나오게 된다.

2. non-repeatable read

read_commited, read_uncommited에서 발생할 수 있다.

한 트랜잭션 내의 같은 행에 두번 이상 조회가 발생했는데, 그 값이 다른 경우를 말한다.

사용자 A가 처음 데이터를 조회했을때 그 값이 100이었다고 가정해보자.

그 후 사용자 B가 그 값을 1로 변경해서 커밋을 한다면, 사용자 A가 다시 조회했을때는 1을 읽게 된다.

이러한 상황과 같이 같은 데이터를 조회했는데, 다른 값을 읽어오는 경우가 반복 가능하지 않은 조회(non-repeatable read) 이다.

 

phantom read와 헷갈릴 수 있으니 예시를 하나 들어보겠다.

1. 트랜잭션 A 시작

2. 트랜잭션 B 시작

3. 트랜잭션 A에서 X쿼리(조회)를 수행한다.

4. 트랜잭션 B에서 Y쿼리(수정, 삽입)를 수행한다.

5. 트랜잭션 B 커밋

6. 트랜잭션 A에서 X쿼리(조회)를 수행한다.

 

non-repeatable read에서는 삽입이 일어나더라도 3번과 6번에서 조회하는 행의 갯수는 같다.

물론 수정한 행의 값은 달라지겠지만 말이다.

하지만 phantom read에서는 3번과 6번에서 조회하는 행의 갯수가 달라진다.

 

3. dirty read

read_uncommited에서 발생할 수 있다.

한 트랜잭션이 실행 중일 때 다른 트랜잭션에 의해 수정되었지만 아직 커밋되지 않은 데이터를 읽을 수 있을 때 발생한다.

위와 같은 상황에서 사용자 B가 값을 1로 변경 후 커밋하지 않았음에도 불구하고 A가 다시 조회했을 때 1을 읽게 된다.

2학기에 프로젝트를 진행할 때 동시성에 대해 고민하게 될텐데, 데이터의 중요도에 따라서 격리수준을 조절해, 속도와 정확성을 최적화 할 수 있을것이라고 생각한다.

728x90