-
트랜잭션의 격리 수준 이라는 등가교환DB 2023. 8. 4. 20:41test
MVCC
RDBMS를 구현하기 위한 개념으로 ACID, Locking, Recovery 등 이 나왔지만
동시성 제어 문제가 발생하였고 이를 해결하기 위해 잠금을 통한 상호배제를 사용했었는데
상호배제로 인해 대기현상이 발생하여 DBMS의 동시성이 낮아지게 되었다
💡 동시성 제어 문제는 대표적으로 Dirty read, Non-repeatable read, Phantom read 등이 있다.
이러한 상호배제로 인해 낮아진 동시성문제를 해결하기 위해 읽기와 쓰기의 결합을 최소화할 수 있는 방법이 나오게 되었는데
그게 바로
동시에 발생하는 트랜잭션 속에서 데이터베이스에 저장된 데이터의 일관성과 격리성을 지킬 수 있도록 도와주는
다중 버전 동시성 제어(MVCC)이다.
MVCC는 SCN이라는 메커니즘을 사용하여 번호 값을 이용하여 트랜잭션 순서를 보장하는 특징이 있기에
특정 시점을 기준으로 commit 된 데이터를 읽을 수 있다
MVCC는 DMBS의 동시성을 위해
'특정 시점'을 통해 ACID 원칙을 다소 희생하여 동시에 실행되는 트랜잭션들이 어디까지 서로에게 영향을 미치지 않을지 정할 수 있는데
그것이 바로 transaction isolation level이다
- READ UNCOMMITTED(커밋되지 않은 읽기)
- READ COMMITTED(커밋된 읽기)
- REPEATABLE READ(반복 가능한 읽기)
- SERIALIZABLE(직렬화 가능)
READ UNCOMMITTED 가 제일 낮은 격리를 제공하고
SERIALIZABLE 가 제일 강한 격리를 제공한다
격리 수준에 따라 해결되는 동시성 문제 가있다.
동시성 문제를 해결할수록, 즉 격리 수준을 엄격하게 가져갈 경우 동시성이 낮아지며
동시성 문제를 어느 정도 수용할 경우, 즉 격리 수준을 느슨하게 가져갈 경우 동시성이 좋아진다.
💡 트랜잭션 은 ACID 원칙을 보장해야 한다
Atomicity(원자성): 작업이 부분적으로 성공하는 일이 없어야 한다
Consistency(일관성): 일관성 있는 데이터 상태를 유지한다
Isolation(독립성): 완료되지 않은 작업에 다른 트랜잭션이 끼어들지 못하게 한다
Durability(영구성): 트랜잭션의 결과가 영구적으로 남아야 한다READ UNCOMMITTED
커밋되지 않은 데이터에 접근 가능한 격리 수준이다.
사실 어떠한 독립성도 없기에 격리 수준이라 부를 수 없다.
Dirty read 발생
A 트랜잭션이 데이터를 변경하거나 추가하고 commit 하기 전에
B 트랜잭션이 해당 데이터를 읽을 때 읽어지는 문제인 dirty read 가 발생한다
예로 아래와 같은 문제가 발생할 수 있다
- A 트랜잭션이 유저의 이름을 “Alice” 에서 “bob” 으로 변경하고 커밋하지 않은 상태에서
B 트랜잭션이 데이터를 읽을 때 “bob”이라 읽게 됨 - A 트랜잭션이 “Alice” 이름을 가진 유저를 추가하고 커밋하지 않은 상태에서
B 트랜잭션이 “Alice” 유저를 읽어서 다른 로직을 수행 중인데 A 트랜잭션이 롤백.
READ COMMITTED
트랜잭션의 변경 내용이 commit 되어야만 다른 트랜잭션에서 조회가능한 격리 수준
오라클 DBMS에서는 기본으로 사용 중이며 가장 많이 선택되는 격리 수준이다.
- A 트랜잭션이 유저의 “Alice”이라는 이름을 “bob” 으로 변경하고 커밋하지 않은 상태에서
B 트랜잭션이 데이터를 읽을 때는 “Alice”이라 읽게 된다.(”Alice” 데이터는 MVCC 영역에 있다)
NON-REPETABLE READ 발생
하나의 트랜잭션에서 같은 값을 조회할 때 다른 값이 조회되는 문제이다.
- A 트랜잭션이 유저를 조회하니 “Alice”이라 조회됨
- B 트랜잭션이 “홍길동” 유저를 조회하여 “bob” 으로 이름을 변경하고 커밋
- A 트랜잭션이 유저를 조회하니 “bob”이라 조회됨
이는 하나의 트랜잭션 내에서는 똑같은 SELECT 수행 시 같은 결과를 반환해야 한다는 REPETABLE READ 정합성이 어긋한 것.
REPETABLE READ
MySQL InnoDB 스토리지 엔진의 기본 격리 수준이다
트랜잭션이 시작되고 종료되기까지 한번 조회한 값은 계속 같은 값이 조회되는 격리 수준이다.
- A 트랜잭션이 유저를 조회하니 “Alice”이라 조회됨
- B 트랜잭션이 “Alice” 유저를 조회하여 “bob” 으로 이름을 변경하고 커밋
- A 트랜잭션이 유저를 조회하니 “Alice”이라 조회됨(MVCC 영역)
이 방법은 자신의 트랜잭션 번호보다 낮은 트랜잭션 번호에서 변경된 내용만 확인하는 방법이다
Phantom Read 발생
REPETABLE READ는 다른 트랜젝션이 update 한 경우에도 변경 전 데이터를 조회할 수 있지만
insert/delete 시에는 영향을 받는 문제가 발생한다.
한 트랜잭션에서 같은 조건으로 데이터를 반복해서 읽었는데
그 사이 다른 트랜잭션이 데이터를 추가해서 처음에는 없었던 데이터가 추가가 되거나
반대로 있었던 데이터가 없어진 상태로 반환하는
즉 다른 트랜잭션의 변경 작업에 의해 데이터가 보였다 안 보이는 문제이다
- A 트랜잭션이 N 개의 유저를 조회
- B 트랜잭션이 유저 추가
- A 트랜잭션이 N 개의 유저를 조회했더니 데이터가 하나 더 보임
Serializable
가장 단순하며 가장 엄격한 격리 수준이다
트랜잭션이 특정 테이블을 읽으면 다른 트랜잭션에서 데이터를 추가, 변경, 삭제할 수 없다.
참고
https://medium.com/monday-9-pm/mvcc-multi-version-concurrency-control-알아보기-e4102cd97e59
https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html
https://joont92.github.io/db/트랜잭션-격리-수준-isolation-level/
'DB' 카테고리의 다른 글
Mysql(Maraidb) 실행 계획 살펴보기 (0) 2023.11.12 db column명은 snake_case 가 최고다 (0) 2023.08.02 FlyWay로 DB 형상 관리 (0) 2023.06.15