격리 수준
다수의 트랜잭션을 병렬적으로 실행하게 되면, 데이터를 읽고 쓰는 과정에서 다양한 문제가 발생할 수 있다.
이로 인해, 데이터의 무결성을 해칠 수가 있으므로 문제 발생을 최대한 방지하기 위해 데이터 베이스에는 격리 수준을 설정하여 동시성 작업에 안정성을 부여할 수 있다.
격리 수준은 4가지로 나누어지며, 격리 수준이 높아질수록 데이터의 무결성을 보장하는 정도가 높아지지만, 제약이 많아지면서 동시성 작업의 효율성이 떨어져 상대적으로 느린 성능을 보유하게 된다.
즉, 격리 수준이란 트랜잭션의 고립 정도를 설정하는 것이며, 그 정도에 따라 데이터의 무결성은 높아지나 속도 측면에선 손해를 보게 된다고 할 수 있다.
격리 수준은 총 4가지로 구분된다.
1. Read Uncomitted
2. Read Committed
3. Repeatable Read
4. Serializable
아래로 갈수록 더 높은 격리 수준을 갖게 된다.
Read Uncomitted
Read Uncomitted란, 이름 그대로 커밋되지 않은 데이터까지 모두 조회할 수 있는 격리 수준을 의미한다.
1번 트랜잭션에서, A사원의 계급을 변경하였으나 아직 커밋하지 않았다고 해보자.
1번 트랜잭션이 A사원의 계급을 변경한 이후 2번 트랜잭션이 A사원의 계급을 조회하게 되면, 변경된 계급을 읽게 된다.
하지만, 1번 트랜잭션이 어떠한 이유로 롤백(Roll Back)하게 된다면?
실제 DB에서 A사원의 계급은 변경되지 않았음에도 불구하고, 2번 트랜잭션은 A사원의 변경된 계급을 기반으로 작업을 실행하게 될 것이다. 이를 Dirty Read라고 한다.
Dirty Read : 아직 작업이 완료되지 않은 트랜잭션에서 변경한 값을 다른 트랜잭션에서 조회하게 되는 상황
Read Uncomitted는 아무런 제약이 없는 만큼 가장 빠른 속력을 보이지만, 그만큼 데이터의 무결성 보장에 있어서는 가장 취약한 고립 수준이다.
Read Comitted
Read Comitted란, 커밋된 데이터에 한해서만 조회할 수 있는 격리 수준을 의미한다.
1번 트랜잭션이 A사원의 계급을 변경하였으나 커밋하지 않았다고 해보자. 해당 작업이 아직 커밋되지 않았으므로 2번 트랜잭션에서는 A사원의 기존의 계급을 조회하게 된다.
하지만, 이런 상황을 가정해보자.
2번 트랜잭션은 A사원의 계급을 총 두 번 조회한다. 첫 번째 조회와 두 번째 조회 사이에, 1번 트랜잭션이 A사원의 계급을 변경하여 커밋한다면? 2번 트랜잭션에서 처음으로 조회했던 A사원의 계급과 두 번째로 조회한 A사원의 계급은 서로 다른 상황이 발생한다. 이는 데이터의 정합성을 해치는 사례이며, Non-Repeatable Read라고 한다.
Non-repeatable Read : 한 트랜잭션에서, 특정 데이터를 여러 번 조회했을 때, 일관되지 않은 값을 조회하는 상황
Repeatable Read
Repeatable Read란, 트랜잭션이 실행되기 이전에 커밋된 내역만 조회할 수 있는 격리 수준을 의미한다.
Read Comitted에서 발생한 Non-repeatable Read 문제의 경우, 트랜잭션 중간에 커밋된 내역을 조회하기 때문에 발생하는 문제이다. 이를 해결하기 위해 Repeatable Read에선, 트랜잭션이 실행 중에 커밋된 내역은 조회할 수 없고 이전에 커밋된 내역에 대해서만 조회할 수 있다.
각 트랜잭션은 커밋하면서, Undo 영역에 커밋하기 이전의 데이터를 백업하게 된다. 이 때, 데이터와 함께 트랜잭션의 번호를 저장하게 되는데 Repeatable Read 고립 수준에선 현재 트랜잭션의 번호보다 낮은 번호의 백업 데이터에 대해서만 접근할 수 있기 때문에, 트랜잭션이 실행중에 커밋된 데이터는 조회할 수 없게 된다.
이로 인해, Non-Repeatable Read 문제는 해결할 수 있지만, 다른 문제점이 한 가지 존재한다.
데이터의 삽입과 삭제의 경우엔, 시기에 상관 없이 조회할 수 있다는 것이다.
1번 트랜잭션에서 id가 3 이상인 모든 튜플을 조회할 것이며, 최초에 id가 3이상인 튜플은 총 3개가 있다고 가정해보자.
1번 트랜잭션이 처음에 id가 3 이상인 모든 튜플을 조회하면 총 3개의 튜플을 확인할 수 있을 것이다.
이후, 2번 트랜잭션이 id가 10인 튜플을 하나 추가했다면, 현재 DB에는 id가 3 이상인 튜플이 총 4개 있을 것이다. 1번 트랜잭션이 다시 id가 3 이상인 튜플을 조회하면, 처음엔 볼 수 없었던 튜플이 추가되어 총 4개의 튜플을 조회하게 된다.
반대로, 중간에 삭제 연산이 발생한다면 처음엔 보였던 튜플이 어느 순간 보이지 않는 상황도 발생할 수 있다.
이처럼, 특정 튜플이 보였다 안보였다 하는 상황을 팬텀 리드라고 한다.
팬텀 리드 (Phantom Read) : 트랜잭션 실행 중, 행이 추가되거나 삭제되면서 보였다 안보였다 하는 상황
(마치 유령을 보는 것과 같다 하여, 팬텀 리드라는 이름이 붙었다고 한다.)
Serializable
Serializable란, 가장 높은 수준의 격리 수준으로 트랜잭션이 사용하는 모든 데이터에 잠금을 거는 격리 수준이다.
한 트랜잭션이 읽거나 쓰는 데이터를 다른 트랜잭션이 절대 접근할 수 없도록 모두 잠궈버리게 된다. 이로 인해, 데이터의 무결성은 완벽히 보장할 수 있지만 동시성 처리가 거의 불가능한 상황이 되어버리므로 매우 느린 속력을 보이게 된다.
'데이터베이스' 카테고리의 다른 글
데이터베이스 (DB) - 데이터의 무결성 (0) | 2024.06.05 |
---|---|
데이터베이스 (DB) - 트랜잭션과 ACID (1) | 2024.06.02 |
데이터베이스 (DB) - 키의 종류 (슈퍼키, 후보키, 기본키, 대체키, 외래키) (1) | 2024.05.31 |
데이터베이스(DB) - 정규화 (제 1 정규화, 제 2 정규화, 제 3 정규화) (1) | 2024.05.31 |