[DATABASE] MVCC 구조와 이해
MVCC 란 ( Multi Version Concurrency Control )
하나의 트랜잭션에서 데이터에 접근하는 경우 데이터의 다중버전 상태 중 보장되는 버전에 맞는 값을 반환하여 처리하는 방법을 의미합니다.
데이터의 다중버전 상태
아래의 단계를 설명하겠습니다.
Step 1. a 에는 30이라는 데이터가 저장되어 있습니다.
Step 3. 트랜잭션1에서 a 는 50 으로 데이터를 갱신했습니다. 이 값을 commit 하기 전입니다.
Step 4. 트랜잭션2에서 a 는 30 으로 데이터가 조회됩니다.
트랜잭션1에서 데이터를 갱신했지만, 트랜잭션 2는 여전히 이전의 값을 조회하고 있습니다.
어떻게 조회할 수 있는것일까요?
데이터를 다중버전 상태로 유지하고 있어 commit 전까지는 이전의 값을 undo 영역에 유지하고 있기 때문입니다.
단계 | 트랜잭션1 | 트랜잭션2 |
step 1 | a = 30 | |
step 2 | begin tran | |
step 3 | update a = 50 | |
step 4 | select a = 30 | |
step 5 | select a = 50 | |
step 6 | commit | |
step 7 | select a = 50 |
MVCC 의 2가지 접근법
첫번째 접근법
PostgreSQL, Interbase, SQL Server 의 DB 에 해당하는 방식입니다.
데이터베이스 내에 다중 버전의 데이터를 저장합니다.
더이상 필요하지 않을 때 데이터를 정리합니다.
데이터베이스 내에 다중 버전의 데이터가 저장되기 때문에,
데이터가 많아지는 형식으로 되어 파일 사이즈가 계속 증가하게 됩니다.
그리고 기존의 데이터는 삭제 표시가 생기게 됩니다.
두번째 접근법
Oracle, MySQL DB 에 해당하는 방식입니다.
최신 버전의 데이터만 데이터베이스 내에 저장합니다.
이전의 데이터는 언두를 이용하여 데이터를 저장합니다.
데이터가 갱신되면 Unco 영역에는 이전 데이터블럭들값과 당시의 SCN가(System Commit Number) 저장되어 있습니다.
SELECT 조회 시 새로운 최신 SCN 의 값을 가지며 이 SCN 값 이전의 블록들 값을 읽게 됩니다.
MVCC 관리 방법
PostgreSQL | Oracle | SQL Server | |
오래된 버전 저장공간 | Heap / Index 영역 | Undo 영역 | tempdb 영역 |
정리 방법 | Vacuum | System Montior Process | Ghost Cleanup Task |
MVCC 저장 방법 ( 디테일하게 )
페이지
데이터 저장공간인 Page 에는 페이지 헤더 / 튜플 / 튜플의 헤더 / 튜플의 위치를 가리키는 포인터들로 저장됩니다.
각각의 튜플에는 데이터들이 저장되어 있다고 보시면 됩니다.
그리고 이 튜플의 헤더는 튜플의 속성값들을 저장합니다.
튜플의 헤더
xmin 은 최신의 값 tmax 는 이전의 값을 의미합니다.
이 포스팅은 MVCC 에 대한부분을 다루기 때문에 t_max 와 t_min 의 의미만 알고 넘어가도록 하겠습니다.
MVCC 저장 방법
상황1
세션0에서 Tuple1 에 A 라고 하는 데이터를 저장 후 Commit 했습니다.
t_xmin 의 값은 2a9 이고, 아직 갱신이 되지 않은 값이기 때문에 t_xmax 는 0 입니다.
이 상태에서 세션1에서 조회를 하면 t_xmin 2a9 에 있는 값을 조회합니다.
상황 2
위 상태에서 세션0에서 Tuple1의 A 값을 B 로 Update 하겠습니다.
Tuple1, B 에 새로운 값이 저장이 되었고 t_xmin 은 2aa 값이 되었습니다.
Tuple1, A 에는 t_xmax 에서 갱신되었다는 의미로 다음값인 2aa 를 저장합니다.
이제 새로 조회하는 세션들은 갱신된 2aa 의 값을 조회하게 됩니다.
이러한 방식으로 계속해서 새로운 데이터로 갱신되면 데이터가 쌓이게 됩니다.
그리고 PostgreSQL 의 경우에는 Vacuum 이라는 내부 기능으로 이전의 데이터들을 정리합니다.
MVCC 조회 방법 ( 디테일하게 )
Oracle
시간정보인 "SCN" 과 공간정보인 "XID" 를 복합적으로 사용하여 트랜잭션을 처리합니다.
Commit SCN 은 트랜잭션이 완료될 때 부여됩니다.
XID 는 위에서말한 xmin, xmax 값들을 구분하기 위한 고유 값입니다.
PostgreSQL, MySQL
트랜잭션이 시작될 때 XID 가 붙여지기 때문에 각각의 snapshot 시점이 필요합니다.
이 포스팅은 아래 경로에서 참고했습니다.