PostgreSQL 17을 다루면서 가장 먼저 눈에 띄는 개념 중 하나는 바로 MVCC (Multi-Version Concurrency Control) 입니다. 사실 MVCC 자체는 PostgreSQL 전용 개념은 아니고, MySQL(InnoDB)도 활용합니다. 하지만 구현 방식운영상의 의미가 다르기 때문에 현업에서 체감 차이가 큽니다.


1. MVCC란 무엇인가?

동시에 여러 트랜잭션이 데이터에 접근할 때, 충돌 없이 읽기/쓰기를 보장하는 기법입니다. 핵심 아이디어는 데이터의 여러 버전을 관리하여 각 트랜잭션이 "자신만의 스냅샷"을 본다는 것입니다.

  • 동시 읽기 보장: SELECT 쿼리는 쓰기 작업에 막히지 않고 이전 버전을 참조합니다.
  • 쓰기 충돌 방지: UPDATE/DELETE는 새로운 버전을 만들어내고, 다른 트랜잭션은 이 버전을 필요할 때만 확인합니다.

2. PostgreSQL의 MVCC 구현

  • 각 행(row)은 내부적으로 xmin, xmax 같은 숨은 컬럼을 가지고 있습니다.
  • 트랜잭션이 실행되면, 현재 스냅샷에 맞는 행 버전만 보이도록 필터링합니다.
  • 오래된 버전(더 이상 참조되지 않는 튜플)은 테이블 안에 그대로 남고, 이후 VACUUM 과정에서 정리됩니다.

➡️ 즉, PostgreSQL은 "행 버전이 테이블 안에 계속 쌓인다 → Autovacuum이 치워준다"라는 구조를 가집니다.


3. MySQL(InnoDB)의 MVCC 구현

  • InnoDB는 Undo Log에 이전 버전을 기록합니다.
  • SELECT 쿼리가 과거 데이터를 필요로 할 때 Undo Log를 거슬러 올라갑니다.
  • 트랜잭션이 종료되면, Undo Log를 Purge Thread가 정리합니다.

➡️ PostgreSQL처럼 테이블 안에 버전이 쌓이는 구조가 아니므로, 별도의 VACUUM은 필요 없습니다.


4. 트랜잭션 격리 수준

PostgreSQL과 MySQL 모두 표준 SQL의 4단계 격리 수준을 지원합니다.

  • PostgreSQL: READ COMMITTED(기본), REPEATABLE READ, SERIALIZABLE
  • MySQL InnoDB: REPEATABLE READ가 기본, READ COMMITTED도 옵션 제공

🔎 차이점: PostgreSQL의 REPEATABLE READ는 사실상 Snapshot Isolation 수준으로 동작하여, MySQL보다 팬텀 리드 방지 측면에서 강력합니다.


5. 실무에서의 체감 차이

  • PostgreSQL:
    • 긴 트랜잭션이 존재하면 VACUUM이 오래된 버전을 정리하지 못해 디스크가 불어남.
    • 따라서 트랜잭션을 짧게 유지하고, Autovacuum 튜닝이 중요합니다.
  • MySQL:
    • Undo Log가 길어지고 Purge Thread가 밀리면 성능 저하.
    • 일반적으로는 DBA가 Undo Tablespace를 관리하거나, 장기 트랜잭션을 피하는 전략을 씁니다.

6. 정리

  • MVCC 자체는 공통 개념이지만,
    • PostgreSQL은 테이블 내부에 버전을 쌓는 구조 → VACUUM 필요.
    • MySQL(InnoDB)은 Undo Log 기반 → Purge Thread 관리.
  • 운영상의 차이가 크기 때문에, DBA 입장에서는 PostgreSQL과 MySQL을 똑같이 취급할 수 없습니다.

다음 편 예고

다음 글에서는 PostgreSQL만의 독특한 개념인 VACUUM을 깊이 다뤄보겠습니다. VACUUM은 PostgreSQL 운영에서 가장 자주 듣는 단어이자, 성능 안정성에 직접적인 영향을 주는 핵심입니다.


 

+ Recent posts