책너두 (데이터 중심 애플리케이션 설계) 23일차 (~259p)
- Book/데이터 중심 애플리케이션 설계
- 2023. 4. 10.
요약
- 트랜잭션의 직렬성에 대해 알게 됨.
- 가장 강력한 격리 수준
- 동시성 없이 직렬로 실행될 때와 같음.
- 실제적인 직렬 실행에 대해 이해함
- 완전히 동시성을 제거함.
- 단일 스레드 처리량을 높이기 위한 방법을 고민해야함.
- 스토어드 프로시저 이용
- 파티셔닝 이용
- 2단계 잠금에 대해 이해함.
- 잠금 요구사항이 더욱 강력해짐.
- 공유, 독점 모드를 이용하여 구현함.
- 잠금을 많이 사용하므로 교착 상태에 잘 빠지게 됨.
- 성능 저하의 원인임.
- 팬텀을 막기 위해서 서술 잠금을 사용함.
- 팬텀을 막을 수 있지만 현실적으로 너무 오래 걸림.
- 색인 범위 잠금을 통해 범위 조건을 타협하고 오버헤드를 낮춘다.
- 잠금 요구사항이 더욱 강력해짐.
메모
직렬성
- 직렬성 격리는 가장 강력한 격리 수준이라고 여겨짐.
- 여러 트랜잭션이 병렬로 실행되도 최종 결과는 동시성 없이 한 번에 하나씩 직렬로 실행될 때와 같도록 보장함.
- 즉, 데이터베이스가 발생할 수 있는 모든 경쟁 조건을 막아줌.
- 그럼에도 사용하지 않는 이유를 알기위해 직렬성 구현 선택지와 동작원리를 이해해야 함.
- 직렬성을 제공하는 데이터베이스는 대부분 세 가지 기법 중 하나를 사용함.
- 트랜잭션을 순차적으로 실행
- 2단계 잠금
- 낙관성 동시성 제어 기법
실제적 직렬 실행
- 트랜잭션을 순차적으로 실행시켜서 동시성을 완전히 제거한다.
- 한 번에 트랜잭션 하나씩만 직렬로 단일 스레드에서 실행하면 됨.
- 단일 스레드를 이용하면 잠금을 코디네이션하는 오버헤드를 피할 수 있다.
- 단일 스레드 처리량은 CPU 코어 하나의 처리량으로 제한됨.
- 따라서, 단일 스레드를 최대한 활용하려면 트랜잭션이 전통적인 형태와는 다르게 구조화돼야 함.
트랜잭션을 스토어드 프로시저 안에 캡슐화하기
- 단일 스레드에서 트랜잭션을 순차적으로 처리하는 시스템들은 상호작용하는 다중 구문 트랜잭션을 허용하지 않음.
- 트랜잭션에 애플리케이션 ↔ 데이터베이스 통신에 많은 시간이 소비되기 때문.
- 애플리케이션은 트랜잭션 코드 전체를 스토어드 프로시저 형태로 데이터베이스에 미리 제출한다.
- 트랜잭션에 필요한 데이터가 메모리에 있고, 스토어드 프로시저를 사용하면 네트워크나 디스크 I/O 대기 없이 매우 빨리 실행된다고 가정한다.
스토어드 프로시저의 장단점
- 단점
- 프로시저용 언어는 라이브러리 생태계가 빈약함.
- 데이터베이스에서 실행되는 코드를 관리하기 어려움.
- 데이터베이스가 애플리케이션 서버보다 훨씬 더 성능에 민감하므로 곤란한 상황이 만들어질 수 있음.
- 위 단점은 기존의 범용 프로그래밍 언어를 사용하여 극복 가능함.
- 장점
- 데이터가 메모리에 저장된다면, 단일스레드에서 실행되면서
- I/O 대기가 필요 없고, 다른 동시성 제어 메커니즘의 오버헤드를 회피하므로 단일 스레드로 상당히 좋은 처리량을 얻을 수 있음.
- 데이터가 메모리에 저장된다면, 단일스레드에서 실행되면서
파티셔닝
- 트랜잭션 순차 실행 시, 단일 CPU 코어의 속도로 제한됨.
- 쓰기 처리량이 높은 애플리케이션에서는 단일 스레드 트랜잭션 처리자가 심각한 병목이 될 수 있음.
- 데이터를 파티셔닝 함으로써 CPU 코어와 여러 노드를 확장시킬 수 있음.
- 각 파티션은 독립적으로 실행되는 자신만의 트랜잭션 처리 스레드를 가질 수 있음.
- 각 CPU 코어에 각자의 파티션을 할당해서 트랜잭션 처리량을 CPU 코어 개수에 맞춰 선형적으로 확장할 수 있음.
- 각 파티션은 독립적으로 실행되는 자신만의 트랜잭션 처리 스레드를 가질 수 있음.
- 여러 파티션에 접근해야 하는 트랜잭션이 있다면 해당 트랜잭션이 접근하는 모든 파티션에 걸쳐서 코디네이션을 해야함.
- 추가적인 오버헤드가 있기에 단일 파티션 트랜잭션보다 엄청 느림.
- 트랜잭션이 단일 파티션에 실행될 수 있는지 여부는 애플리케이션에 사용되는 데이터 구조에 매우 크게 의존함.
- ex) 키-값 데이터 → 쉽게 파티셔닝 가능
- ex) 여러개의 보조 색인 → 여러 파티션에 걸친 코디네이션이 필요할 가능성이 높음.
2단계 잠금(2PL)
- 30년간 데이터베이스에서 직렬성을 구현하는데 널리 쓰인 유일한 알고리즘이 바로 2단계 잠금(two-phase locking, 2PL)임.
- 더티 쓰기의 잠금과 비슷하지만, 잠금 요구사항이 훨씬 더 강함.
- 2PL은 쓰기 트랜잭션은 다른 쓰기 트랜잭션 뿐만 아니라 읽기 트랜잭션도 진행하지 못하고 그 역도 마찬가지임.
- 반면, 스냅숏 격리는 읽는 쪽이 결코 쓰기를 막지 않고, 그 역도 마찬가지임.
- 이게 스냅숏 격리와 2PL 의 중요한 차이점임.
2단계 잠금 구현
- 읽는 쪽과 쓰는 쪽을 막는 것은 데이터베이스의 각 객체에 잠금을 사용하여 구현함.
- 잠금은 아래 모드로 사용될 수 있음.
- 공유 모드(shared mode)
- 독점 모드(exclusive mode)
- 잠금은 다음과 같이 사용됨.
- 읽기 시, 공유 모드로 잠금을 획득한다.
- 만약 해당 객체에 독점 모드로 잠금을 획득한 트랜잭션이 있으면, 다른 트랜잭션은 이 트랜잭션이 끝날 때 까지 기다려야 함.
- 트랜잭션이 객체에 쓰기를 원하면 독점 모드로 잠금을 획득해야 함.
- 트랜잭션이 객체를 읽다가 쓰기를 실행하려면 공유 잠금 → 독점 잠금으로 업그레이드 해야 함.
- 읽기 시, 공유 모드로 잠금을 획득한다.
- 잠금은 아래 모드로 사용될 수 있음.
- 이렇게 잠금을 많이 가지고 있으면 A 가 B 를 기다리고 B 가 A 를 기다리는 상황이 쉽게 발생할 수 있음.
- 교착 상태라고 함.
- 데이터베이스는 두 트랜잭션 중 하나를 어보트 시키고, 다른 트랜잭션을 진행하게 됨.
- 어보트된 트랜잭션은 애플리케이션에서 재시도 해야 함.
- 교착 상태라고 함.
2단계 잠금의 성능
- 2단계 잠금의 큰 약점은 성능이다.
- 완화된 격리 수준을 쓸 때보다 트랜잭션 처리량과 질의 응답 시간이 크게 나빠짐.
- 여러 트랜잭션이 같은 객체에 접근하려고 하면 대기열이 생겨서 여러 달느 트랜잭션이 완료되기를 기다려야 할 수 있음.
- 완화된 격리 수준을 쓸 때보다 트랜잭션 처리량과 질의 응답 시간이 크게 나빠짐.
- 교착 상태도 빈번히 발생할 수 있음.
- 교착 상태가 되면 작업을 재시도해야 하기에 헛수고가 심하게 됨.
서술 잠금
- 팬텀을 막기 위해서는 개념적으로 서술 잠금(predicate lock)이 필요함.
- 특정 객체에 속하지 않고, 검색 조건에 부합되는 모든 객체에 속한 얘들을 잠근다.
- 서술 잠금의 핵심 아이디어는 데이터베이스에 아직 존재하지 않지만 미래에 추가될 수 있는 객체(팬텀)에도 적용할 수 있다는 것임.
색인 범위 잠금
- 서술 잠금은 유감스럽게도 잘 동작하지 않음.
- 진행 중인 트랜잭션들이 획득한 잠금이 많으면, 조건에 부합하는 잠금을 확인하는데 시간이 오래 걸리기 때문.
- 따라서 2PL이 지원하는 대부분의 데이터베이스는 실제로 색인 범위 잠금(index-range locking = 다음 키 잠금 (next-key locking)을 구현함.
- 반드시 필요한 조건으로 잠금을 걸기 보다는 그보다 큰 범위로 잠금을 거는 것이다.
- 그만큼 색인 범위 잠금은 서술 잠금보다는 정밀하지 않지만, 오버헤드가 훨씬 더 낮기 때문에 좋은 타협안이 됨.
'Book > 데이터 중심 애플리케이션 설계' 카테고리의 다른 글
책너두 (데이터 중심 애플리케이션 설계) 25일차 (~284p) (0) | 2023.04.18 |
---|---|
책너두 (데이터 중심 애플리케이션 설계) 24일차 (~272p) (0) | 2023.04.10 |
책너두 (데이터 중심 애플리케이션 설계) 22일차 (~250p) (0) | 2023.04.08 |
책너두 (데이터 중심 애플리케이션 설계) 21일차 (~245p) (0) | 2023.04.07 |
책너두 (데이터 중심 애플리케이션 설계) 20일차 (~241p) (0) | 2023.04.06 |