데이터베이스는 여러 사용자와 애플리케이션이 동시에 접근하여 데이터를 읽고 쓰는 환경에서 작동합니다. 이러한 동시 접근 상황에서 데이터의 정확성과 일관성을 유지하는 것은 매우 중요한 과제입니다. 만약 적절한 제어 없이 동시 트랜잭션이 발생한다면, ‘잘못된 읽기(Dirty Read)’, ‘반복 불가능한 읽기(Non-Repeatable Read)’, ‘유령 읽기(Phantom Read)’와 같은 문제들이 발생하여 데이터 무결성이 손상될 수 있습니다.
전통적인 동시성 제어 방식은 주로 ‘잠금(Locking)’을 사용하여 데이터 접근을 제어했습니다. 쓰기 트랜잭션이 데이터를 수정하는 동안 해당 데이터에 대한 다른 트랜잭션의 접근을 막아 일관성을 보장하는 방식이죠. 하지만 이는 심각한 성능 저하, 교착 상태(Deadlock) 발생 위험, 그리고 읽기 작업이 쓰기 작업을 차단하거나 그 반대의 상황이 발생할 수 있다는 단점을 안고 있습니다.
이러한 문제들을 해결하고 동시성을 극대화하기 위해 등장한 혁신적인 기술이 바로 다중 버전 동시성 제어(Multi-Version Concurrency Control, MVCC)입니다.
MVCC는 데이터베이스가 특정 데이터의 여러 버전을 동시에 유지하고, 각 트랜잭션이 자신의 시작 시점에 해당하는 데이터 스냅샷을 볼 수 있도록 함으로써 동시성 문제를 해결합니다. “읽기(Reader)는 쓰기(Writer)를 블록하지 않고, 쓰기는 읽기를 블록하지 않는다”는 철학을 기반으로 합니다.
tx_start_id)와 종료된 트랜잭션 ID(tx_end_id) 같은 메타데이터를 포함합니다.Products 테이블에 inventory 필드가 있다고 가정해 봅시다. MVCC 환경에서는 하나의 데이터가 업데이트될 때마다 새로운 버전이 생성됩니다.
초기 상태 (트랜잭션 ID 1000에서 커밋되었다고 가정):
| id | name | inventory | tx_start_id | tx_end_id |
|---|---|---|---|---|
| 1 | Laptop | 100 | 1000 | NULL |
시나리오:
tx_id = 1001
id = 1인 Laptop의 inventory를 조회합니다.1001) 기준으로 유효한 행을 찾습니다. (tx_start_id <= 1001 이고 tx_end_id IS NULL OR tx_end_id > 1001 조건을 만족)inventory = 100을 읽습니다.tx_id = 1002
id = 1인 Laptop의 inventory를 90으로 업데이트합니다.id = 1인 기존 행의 tx_end_id를 1002로 설정합니다.id = 1인 새 행을 inventory = 90, tx_start_id = 1002, tx_end_id = NULL로 삽입합니다.업데이트 후 상태 (트랜잭션 B 커밋 전):
| id | name | inventory | tx_start_id | tx_end_id |
|---|---|---|---|---|
| 1 | Laptop | 100 | 1000 | 1002 |
| 1 | Laptop | 90 | 1002 | NULL |
계속되는 동작:
1001) 기준으로 데이터를 조회하므로, tx_start_id <= 1001 AND (tx_end_id IS NULL OR tx_end_id > 1001) 조건에 따라 첫 번째 행을 선택하여 inventory = 100을 계속 읽습니다. 트랜잭션 B의 변경사항에 전혀 영향을 받지 않습니다.tx_id = 1003 (트랜잭션 B가 커밋된 후)
id = 1인 Laptop의 inventory를 조회합니다.tx_start_id <= 1003 AND (tx_end_id IS NULL OR tx_end_id > 1003) 조건에 따라 두 번째 행을 선택하여 inventory = 90을 읽습니다. 트랜잭션 B의 최신 변경사항을 보게 됩니다.이처럼 MVCC는 여러 버전의 데이터를 동시에 유지하며, 각 트랜잭션이 자신의 시작 시점 스냅샷에 해당하는 데이터를 일관성 있게 볼 수 있도록 합니다.
MVCC는 현대 관계형 데이터베이스(PostgreSQL, MySQL InnoDB, Oracle, SQL Server의 Snapshot Isolation 등)에서 고성능과 높은 신뢰성을 동시에 달성하기 위한 핵심 기술입니다. 데이터베이스가 복잡한 동시성 요구사항을 처리하면서도 데이터 무결성을 굳건히 지킬 수 있도록 돕는 MVCC는 오늘날 우리가 빠르고 안정적으로 데이터를 이용할 수 있게 하는 숨은 마법사라고 할 수 있습니다.
MVCC의 이해는 데이터베이스 시스템의 동작 원리와 성능 최적화 전략을 깊이 있게 파악하는 데 필수적인 요소이며, 동시성 문제에 직면했을 때 효과적인 해결책을 모색하는 데 큰 도움이 될 것입니다.
Text by Chaelin & Gemini. Photographs by Chaelin, Unsplash.