[Database] Postgres의 MVCC

김지환·2023년 5월 6일
0

TL;DR

RDBMS는 동시성제어의 방식으로 MVCC를 사용하고 있다. MVCC ( Multi-Version Concurrency Control )란 데이터 일관성을 확보하기 위해서 데이터에 대한 버전관리를 통해서 이를 해결한 방식이다. 그 말인즉 데이터를 쿼리하기 위해 Transaction을 만들었다면 해당 Transaction은 데이터의 스냅샷 ( Snapshot ) 을 보고 있는 것이다.

이러한 방식을 통해서 Reading 하는 작업에 대해서 Locking을 걸지 않고 진행을 할 수 있기 때문에 높은 성능을 얻을 수 있게 된다.

MVCC를 구현하는 방법

RDBMS 마다 MVCC를 구현한 방식이 다르다. 개념 자체는 동일하지만 버전관리를 어떻게 하느냐에 따라서 차이가 생긴다. 가장 많이 사용되고 있는 RDBMS인 MySQL(InnoDB), Postgres의 구현 방법을 알아볼 예정이다. 이번 포스팅에서는 Postgres의 방식을 먼저 살펴보자.

PostgreSQL의 MVCC

PostgreSQL 에서는 record를 tuple이라고 부른다. PostgreSQL에서는 멀티버전에 대한 정보를 하나의 Page ( Table )에서 관리하고 있다.

모든 테이블에는 System Columns을 가지고 있다. predefined 된 컬럼들로 내부 동작에 사용된다. 이 컬럼중 mvcc를 구현하게 해주는 것이 xmin, xmax 컬럼이다.

xmin은 새로 삽입되거나 변경된 tuple에 현재 txID를 넣어주게 되고 xmax는 null값을 갖게 된다. 만약 삭제나 변경이 일어난다면 이전 tuple의 xmax에는 작업을 시행한 txID 값이 들어가게 되는 것이다.

PostgreSQL MVCC의 문제점

이렇게 하나의 page에 이전 tuple들이 남겨지기 때문에 실제 보여지는 row는 적어보이지만 용량은 그대로 차지하는 경우가 있다. 또한 쿼리 성능 또한 지속적으로 떨어지게 된다. ( 이전 tuple이 page에서 사라진게 아니기 때문에 ) 따라서 PostgreSQL 에서는 Vacuum 작업을 진행해줘야한다.

vaccum 작업은 manually 진행할 수도 있지만 ( e.g.) vacuum {table_name}; 특정 조건이 맞으면 자동으로 진행되게 되어있다.

  • Dead Tuple의 개수가 임계치에 도달했을 때
  • Table이나 Tuple의 age가 임계치에 도달했을 때

AutoVacuum을 진행했다고 해서 table의 용량이 줄어들지는 않는데 이는 Fully vaccum을 진행하지 않고 Standard Vacuum을 진행하기 때문이다. Fully vaccum을 하게 되면 Exclusive Lock이 걸리게 되어서 DML 동작이 되지 않는 문제가 생기기 때문에 운영단계에서는 절대 해서는 안된다.

AGE 란?

Autovacuum의 조건중 하나로 age가 있는데 age란 tuple이 처음 생길 때 1로 부여되고 그 후 Transaction이 발생할 때 마다 1씩 증가하게 된다.

Dead tuple이 많아지면 성능 저하의 이슈가 있긴 하지만 시스템에 당장 크리티컬하게 작용하지는 않는다. 하지만 Transaction ID Wraparound 이슈가 발생하면 이야기가 다르다.

Transaction ID는 4byte로 2^32 = 약 40억개의 ID를 부여할 수 있다. 여기서 절반을 나눠서 20억개는 과거 20억개는 미래데이터를 위해 사용한다. 하지만 계속해서 txID 가 증가하게 되어서 overflow가 일어나면 1이 되게 되는데 이러면 이전 과거의 데이터들이 모두 미래의 데이터가 되버리는 이상한 상황이 초래된다.

이러한 상황을 막기 위해서 Anti Wraparound Vacuum이 존재한다. 이 때 기준이 되는 것이 바로 age 값이다. 이 age 값이 임계치를 넘게되면 vaccum이 진행되는 것이다. ( 5천만이 기본값)

Reference

https://techblog.woowahan.com/9478/
https://www.postgresql.org/docs/9.1/ddl-system-columns.html

profile
Developer

0개의 댓글