티스토리 뷰
목차
- ACID
- 동시성 문제
- Dirty Read, Non-Repeatable Read, Phantom Read
- 더티 쓰기 (dirty write)
- 갱신 손실 (lost update)
- 쓰기 스큐 (write skew)
- 참고문헌
ACID
동시성의 이야기를 진행하기 전에 먼저 ACID를 다루고자 한다. Atomicity 원자성, Consistency 일관성, Isolation 격리성, Durability 지속성이 있다. 원자성과 격리성은 동시성을 다루기전에 한번 짚고 넘어갈 만한 이야기다.
원자성은 쪼갤 수 없는 어떤 것을 말한다. 데이터베이스는 어떤 작업들의 절차들을 하나의 쪼갤 수 없는, 트랜잭션을 정의할 수 있다. 그리고 일련의 작업 중 어떤 것이 실패하였을 때 전부 되돌릴 수 있다. 엄밀히 말하면 동시성과 직접적인 관련은 없다. 하지만 격리레벨을 말 할 때 트랜잭션이 함께 등장하긴 하며, 동시성 결함을 감지하는 낙관적 잠금(~직렬성 스냅샷 격리)를 사용할 때 이전 버전이 무사히 롤백 될 수 있는 것도 원자성이란 특징 때문이다. 하지만 원자성 자체가 동시성이 발생할 때 어떤 작업을 하는지는 직접적으로 관련이 없다.
격리성은 동시에 실행되는 트랜잭션은 서로 격리된다는 것을 의미한다. 트랜잭션이 동일한 자원에 접근할 때, 동시성 문제가 발생한다. 모든 트랜잭션이 직렬적으로 동작한다면(단 하나의 트랜잭션만 열릴 수 있다면) 완벽히 모든 작업들은 격리되며 문제가 없을 것이다. 하지만 데이터베이스는 보다 완화된 격리 방식(~스냅샷 격리)으로 격리를 보장한다. 현대적인 데이터베이스는 완화된 격리를 지향하며 설계되기 때문이다.
동시성 문제
동시성 문제란 여러 프로세스나 스레드가 동시적으로 같은 자원을 참조하여 생기는 문제를 말한다. 가장 쉬운 예는 같은 자원에 대하여 변경을 하는 더티 쓰기 문제가 있다. 그뿐만이 아니라, 이전에 우리가 다루었던 dirty read, non-repeatable read, phantom read등이 있다.
한번 더 살펴보면서, 잠금에 대해서 이야기를 진행하고자 한다.
Dirty Read, Non-Repeatable Read, Phantom Read
Dirty Read: 한 연산이 데이터를 읽을 때, 다른 트랜잭션이 커밋하지 않은 변경한 것을 그대로 읽고 프로세스를 진행하는 문제이다. 값을 변경한 트랜잭션은 아직 커밋하지 않았으므로 해당 데이터가 정상적으로 커밋될지, 어보트될지는 아직 미정된 상태이기 때문에 다른 연산이 변경된 값을 참조하여 로직을 진행하는 것은 판단에 달려있고, 커밋되지 않은 값을 가져오는 상황은 대부분 혼란을 야기한다.
Non-Repeatable Read: 한 트랜잭션이 데이터를 읽을 때, 다른 트랜잭션이 커밋한 값을 읽는 문제이다. 값을 변경한 트랜잭션은 커밋을 완료하였고, 롤백가능성이 없다. 하지만 주 트랜잭션이 비즈니스 로직을 진행할 때 다른 트랜잭션이 커밋하기 전 기준으로 시작하였으나, 커밋하기 후의 데이터를 읽었을 때 다르다면 주 트랜잭션이 혼란을 받는다.
Phantom Read: 한 트랜잭션이 데이터를 읽을 때, 다른 트랜잭션이 커밋한 값을 읽는 문제이다. 하지만 여기서 Non-Repeatable 과 다른 점은 같은 레코드를 다시 읽는 것이 아니라, 같은 테이블의 데이터를 읽지만 다른 레코드가 추가되는 것을 읽는 것이다. 앞서 살펴본 동시성 문제는 읽기문제에 관련된 것이다. 그리고 트랜잭션 격리 레벨을 높이면 해결할 수 있다. 하지만 Phantom Read는 Serializable로 올리지 않는 이상 올리지 않는 이상 해결 할 수 없으며, Serializable은 현대적인 데이터베이스에서 지양하는 격리 레벨이다.
위 살펴본 동시성 문제는 주로 읽기 문제이다. 쓰기문제에 대해서 알아보겠다.
더티 쓰기 dirty write
더티 쓰기란 두 트랜잭션 중 한 트랜잭션이 수정 한 것을 커밋이나 롤백이 이루어지기 전에 다시 써버리는 작업이다. 이후에 변경한 현대적인 RDBMS에서 실험해볼 수 없는 기능이다. 왜냐하면 UPDATE에 대하여 X-Lock을 걸기때문에, 한 트랜잭션이 업데이트를 커밋하거나 롤백하기 전까지 다른 트랜잭션은 해당 레코드를 업데이트할 수 없다. 하지만 그러한 것이 없었던 옛날에는, 개념상으로 더티 쓰기가 존재하였다.
갱신 손실 lost update
갱신 손실은 두 트랜잭션이 트랜잭션을 시작할 때 같은 버전의 스냅샷을 읽어 각각 업데이트를 하는 것이다. 이 경우 두 업데이트중 하나만 정상적으로 적용이 된다. 한 갱신 작업은 손실된다.

쓰기 스큐 write skew
쓰기 스큐란 두 트랜잭션이 서로 다른 두 레코드를 삽입 또는 업데이트하는 것이다. 문제는, 두 트랜잭션이 수행한 로직이 같은 비즈니스 로직을 수행하여 각각의 레코드를 정당하게 업데이트 하였는데 전체적으로 보면 경쟁 조건인것이다. 호출 대기 문제는 아주 좋은 예다. 아래는 두 담당자가 현재 대기 인원이 2명이면 본인은 쉬려고 하는 예제이다. 하지만 두 트랜잭션 모두 최근 스냅샷이 대기 인원이 2명이였기에 둘 모두 off를 할 수 있었다. 하지만 트랜잭션이 모두 커밋된 이후는 대기인원이 아무도 남아있지 않고 최소 조건을 만족하지 않는다.

쓰기 스큐는 복잡한 예가 아니다. 동시에 회의실을 예약할 때 동일한 시간대에 예약이 없으면 해당 방에 예약을 추가 하는 문제도 포함된다. 아래는 A, B 사용자가 룸 1에 예약이 없는 것을 확인하고 예약을 하는 예제이다. 둘 모두 가장 최근 스냅샷에서 비어있는 것을 확인하였고, 룸 1에 예약을 하지만, 두 트랜잭션이 모두 끝난 후에는 동일 시간대에 룸 1에 대한 예약 레코드가 두개 생기게 된다.

또 다른 예로는 사용자명 획득에 대한 예제이다. 동일한 사용자명은 생성되면 안되지만, 두 동일한 사용자명이 생성되는 예제이다.

다음 포스팅에서는
스냅샷 격리, 직렬성 격리, 직렬성 스냅숏 격리 에 대해서 알아볼것이다.
더 쉽게 말해서, MVCC, 트랜잭션 격리, 비관적 락, 낙관적 락에 대해서 알아볼것이다.
참고문헌
- 데이터 중심 애플리케이션 설계
'데이터베이스' 카테고리의 다른 글
| 트랜잭션과 동시성(락) (3) (0) | 2025.11.19 |
|---|---|
| 트랜잭션과 동시성(락) (1) (0) | 2025.10.26 |
| 인덱스 (0) | 2022.01.18 |
| 트랜잭션과 ACID 성질 (0) | 2022.01.16 |
| 인강 1) 관계 대수와 SQL (0) | 2021.06.29 |
- Total
- Today
- Yesterday
- 이산 수학
- 트랜잭션
- arena simulation
- Propositional and Predicate Logic
- Discrete Mathematics
- 대규모 시스템 설계 기초
- 그라파나
- 자바스크립트
- paul wilton
- grafana cloud
- Arena
- 아레나
- rosen
- 항해99
- 데이터 중심 애플리케이션 설계
- 아레나시뮬레이션
- 자바스크립트 예제
- 동시성
- 명제논리
- javascript
- 최단경로 알고리즘
- 엄청난 인내심과 시뮬레이션을 위한 아레나 툴
- 백준
- Simulation
- 가상 면접 사례로 배우는 대규모 시스템 설계 기초
- 로젠
- beginning javascript
- 아레나 시뮬레이션
- 이산수학
- 시뮬레이션
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |