Today I Learned
(24.12.12) 관계형 DB의 격리수준
채용 공고를 보거나 RDB를 충분히 다룰 수 있다는 있는 역량을 보는 것과 동시에,
Spring Framework 에서의 JPA를 활용하면서, Transaction 전파 전략(Propagation) 설정하는 선에서 Transaction 을 다루고자 했다.
하지만, SQL을 활용해서 DB 내에서 Transaction간 격리수준을 설정하는 것만으로 Session 별 또는 Global로 Transaction간 읽기 쓰기에 대한 동시성 제어가 가능할 수 있기 때문에,
Spring 단이 아닌 DB 단에서 격리 수준을 다루기 위해 찾아보고 정리를 했다.
관계형 DB의 격리수준
DB의 격리 수준
트랜잭션 간 동시성 제어를 위한 독립성 보장하는 설정
- 여러 트랜잭션이 동시에 실행될 때 서로의 작업에 간섭하지 않도록 조정
- 데이터의 일관성과 무결성을 유지 → 경쟁 상태를 최소화
- 일관성 Independence
- 논리적 구조와 응용프로그램, 물리적 구조(저장구조)가 서로 변경되더라도 영향을 주지 않는 것
- 무결성 Integrity
- 데이터의 정확성 + 일관성을 보장, DB에 저장된 데이터가 정확, 일관된 유효한 상태인것
- 일관성 Independence
중간 상태 데이터를 볼 수 있도록 정의 하는 설정
- 각 트랜잭션이 실행 중에 다른 트랜잭션이 수행한 변경 사항 (데이터)을 볼 수 있는지를 결정
- DB 내 트랜잭션 간의 데이터 공유 범위를 제어
- 트랜잭션 간 영향을 준다는 의미 X
주요 격리 수준
-- 전체(글로벌) 격리 수준 설정
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITED(아래 격리수준);
-- 세션 격리 수준 설정
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITED(아래 격리수준);
-- 현재 글로벌 격리 수준 확인
SELECT @@global.transaction_isolation;
-- 현재 세션 격리 수준 확인
SELECT @@transaction_isolation;
READ UNCOMMITED
- 트랜잭션이 커밋되지 않은 데이터를 다른 트랜잭션이 읽을 수 있는 가장 낮은 격리 수준
- Dirty Read 발생 가능
- 아직 커밋되지 않은 데이터를 읽음 →데이터의 무결성이 깨질 수 있음
- Dirty Read 발생 가능
- 높은 동시성을 제공하지만 데이터 무결성 보장 불가 = 짧게 정리해서 안전하고 신뢰할만한 데이터가 아니라는 점
- 주로 테스트 또는 성능이 중요한 특정 작업에서 사용
READ COMMITED
- 트랜잭션이 커밋된 데이터만 다른 트랜잭션이 읽을 수 있는 격리 수준
- Non-Repeatable Read 발생 가능
- 동일 트랜잭션 내에서 같은 데이터를 여러 번 조회 시, 다른 결과가 반환될 가능성
- Non-Repeatable Read 발생 가능
- Dirty Read는 방지
- 대부분의 DBMS(Oracle, SQL Server)에서 기본으로 사용하는 격리 수준
- 성능과 데이터 무결성간 균형이 적절하여 일반적으로 많이 사용
- 흔히 아는 그 격리 수준
REPEATABLE READ
- 트랜잭션 시작 후 동일 데이터를 여러 번 읽어도 항상 같은 결과를 반환하는 격리 수준
- 데이터 스냅샷을 보장해서 그 스냅샷에서 데이터를 계속 가져오는 형태
- Phantom Read 발생 가능
- 동일한 조건으로 데이터를 조회 시, 이전에는 없던 새로운 데이터가 나타나는 문제
- Non-Repeatable Read, Dirty Read도 방지
- MySQL에서는 기본 격리 수준으로 사용
SERIALIZABLE
- 모든 트랜잭션을 순차적으로 실행하여 동시성 문제를 완전히 방지하는 가장 높은 격리 수준
- autocommit이 안되어있는 이상, 다른 트랜잭션에서도 잠금이 걸린 상태
- → Deadlock 걸릴 확률
- Phantom Read, Non-Repeatable Read, Dirty Read 모두 방지
- 트랜잭션 간 충돌을 완전히 차단하기 때문에 데이터 무결성 최상으로 보장
- 동시성 처리 능력이 크게 저하되어 성능 문제가 발생할 수 있음
- 동시 트랜잭션 수가 적고 데이터 정확성이 매우 중요한 환경에서 사용
격리 수준 | 특징 | 발생 가능 문제 | 주로 사용되는 환경 |
READ UNCOMMITTED | 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있는 가장 낮은 격리 수준 | Dirty Read 커밋되지 않은 데이터를 읽음 |
테스트 또는 성능이 중요한 특정 작업 |
READ COMMITTED | 커밋된 데이터만 읽을 수 있는 격리 수준 | Non-Repeatable Read 동일 데이터를 여러 번 조회 시 다른 결과 가능 |
대부분 DBMS 기본 격리 수준성능과 무결성 균형 |
REPEATABLE READ | 트랜잭션 시작 후 동일 데이터를 여러 번 읽어도 항상 같은 결과를 반환 | Phantom Read 조회 시 새로운 데이터가 나타남 |
MySQL 기본 격리 수준트랜잭션 내 데이터 일관성 보장 |
SERIALIZABLE | 모든 트랜잭션을 순차적으로 실행하여 동시성 문제를 방지 | - | 데이터 정확성이 중요한 환경동시 트랜잭션 수가 적을 때 |
Phantom Read 방지 매커니즘
- 대부분의 애플리케이션에서 요구하는 수준의 데이터 일관성을 제공
- SERIALIZABLE의 성능 이슈에 비해 균형잡혀있기 때문에 MySQL에서 채택
갭 잠금 (Gap Lock)
- 인덱스에서 레코드 간의 간격(Gap)을 잠그는 방식
- WHERE id > 10 AND id < 20 조건에서 (10, 20) 사이의 간격에 대해 잠금이 설정 하는 방식
- 단, 데이터의 직접적인 값을 수정하는 것이 아닌 그 인덱스의 순서에 관여된 삽입이나 인덱스 이동이 제한되는 것
- id를 변경 하는 등
- 트랜잭션이 실행 중인 범위에 다른 트랜잭션이 새로운 레코드를 삽입할 수 없도록 보호
- 인덱스(따로 인덱스 테이블이 아닌 id 등이 기준)를 통한 검색 시 적용, 기존 데이터의 변경을 막지 않고 간격에 새로운 데이터 삽입을 막음
넥스트 키 락 (Next-Key Lock)
- 레코드와 그 레코드 다음 위치의 간격을 동시에 잠그는 방식
- 순서는 데이터의 id 기준 unique 값을 기본, 다른 인덱스가 기준이 된다면 그 인덱스를 기준으로 진행
- name을 기준으로 한다면 알파벳 순서 등으로 기준이 정해지는 방식
- 레코드에 대한 수정 및 삽입을 동시에 방지
- 갭 잠금과 동일하게 새로운 데이터 삽입을 방지 + 데이터 자체의 수정도 막음
- WHERE id = 10에서 해당 레코드와 그 다음 레코드 간의 간격을 잠가, 다른 트랜잭션이 해당 위치에 삽입 또는 수정할 수 없도록 하는 방식
다음은 각각의 상황을 SQL로 어떠헥 다룰 수 있을 건지 간단하게 적으면서 확인을 하고,
트랜잭션간 WRITE READ 경합 상황 등을 가정해서 어떻게 이뤄질 수 있는지 정리를 할 것
'Today I Learned' 카테고리의 다른 글
(25.01.15) BFS 알고리즘의 메모리 부족 Memory Limit 해결 (0) | 2025.01.15 |
---|---|
(24.12.18) MVCC 매커니즘 (1) | 2024.12.18 |
(24.11.25) DP(Dynamic Programming) 과 전체탐색(BFS, DFS)에 대한 정리 (0) | 2024.11.25 |
(24.11.18) BFS를 활용한 도현의 외각선 탐색 (0) | 2024.11.18 |
(24.11.11) BFS를 활용한 미로 최단 거리 찾기 (0) | 2024.11.11 |