본문 바로가기
CS/DataBase

Postgresql

by BK0625 2026. 3. 12.
반응형

1. 강력한 객체-관계형 기능과 확장성 (Extensibility)

PostgreSQL은 단순한 관계형 모델을 넘어선 **객체-관계형 데이터베이스(ORDBMS)**의 특성을 가집니다. 이는 데이터베이스의 핵심 기능을 사용자가 직접 확장하고 정의할 수 있는 유연성을 제공합니다.

  • 사용자 정의 타입(User-Defined Types):
    • 설명: 데이터베이스가 기본으로 제공하는 INTEGER, VARCHAR, TIMESTAMP 등의 타입 외에, 개발자가 직접 새로운 데이터 타입을 정의하여 사용할 수 있습니다. 이 타입에는 해당 타입에 맞는 연산자(+, 등), 함수, 인덱스 등을 함께 정의할 수 있습니다.
    • 장점:
      • 데이터의 의미 정확성: 특정 도메인의 데이터를 DB 스키마 수준에서 더 정확하게 표현할 수 있습니다. 예를 들어, ipv4_address나 email_address 같은 타입을 직접 만들어 유효성 검사 로직을 타입 정의에 포함시킬 수 있습니다.
      • 코드의 재사용성 및 일관성: 애플리케이션 계층에서 반복적으로 처리해야 할 유효성 검사나 변환 로직을 DB 내부로 가져와 일관된 처리를 보장합니다.
      • 성능 향상: DB가 해당 타입을 더 효율적으로 저장하고 처리할 수 있도록 최적화될 가능성이 있습니다.
    • 예시: IP 주소 문자열을 저장하는 대신 inet 또는 cidr 타입으로 저장하여 IP 네트워크 연산(예: 특정 서브넷에 속하는지 확인)을 DB 내부에서 직접 수행할 수 있습니다.
  • 사용자 정의 함수 및 연산자(User-Defined Functions & Operators):
    • 설명: SQL, PL/pgSQL(PostgreSQL의 내장 절차형 언어), C, Python, Perl, R 등 다양한 프로그래밍 언어로 함수를 작성하여 데이터베이스에 등록할 수 있습니다. 이 함수들은 쿼리 내에서 일반 함수처럼 사용될 수 있으며, 새로운 연산자(예: @@ 같은 사용자 정의 검색 연산자)를 정의하여 특정 데이터 타입에 대한 동작을 확장할 수 있습니다.
    • 장점:
      • 비즈니스 로직 캡슐화: 복잡한 비즈니스 로직 일부를 DB 함수로 구현하여 쿼리 내에서 재사용하고, 클라이언트 애플리케이션의 부담을 줄일 수 있습니다.
      • 확장성: 기존 SQL이 제공하지 않는 특정 계산이나 데이터 처리 로직을 DB에 직접 추가할 수 있습니다.
      • 성능: DB 내부에서 실행되므로 클라이언트-서버 간 데이터 전송 없이 효율적인 처리가 가능합니다.
    • 예시: 특정 좌표계 변환 함수를 C로 작성하여 PostgreSQL에 등록한 후, GIS 쿼리에서 이 함수를 직접 사용하여 효율적으로 지리 데이터를 처리할 수 있습니다.
  • 강력한 확장 프로그램(Extensions):
    • 설명: PostgreSQL은 모듈식 아키텍처를 채택하여, 코어 시스템을 수정하지 않고도 강력한 추가 기능을 "확장" 형태로 설치할 수 있습니다. 이는 마치 운영체제의 플러그인과 같습니다.
    • 장점:
      • 기능 확장 용이성: 특정 도메인에 특화된 기능을 DB에 쉽게 추가할 수 있습니다.
      • 안정성: 코어 시스템에 영향을 주지 않으므로 안정성이 높습니다.
      • 활발한 커뮤니티: 다양한 활용 사례에 대한 풍부한 확장 프로그램들이 개발되어 있습니다.
    • 예시:
      • PostGIS: 공간 데이터(지리 정보)를 저장, 쿼리, 분석하기 위한 업계 표준 확장입니다. POINT, LINE, POLYGON 같은 지리적 데이터 타입을 제공하고, 거리 계산, 포함 여부 확인 등 수백 가지의 공간 함수를 제공하여 지도, 위치 기반 서비스, 자율 주행 등에 필수적입니다.
      • pg_trgm: 텍스트 유사성 검색을 위한 확장입니다. "trigram"(3개의 연속된 문자열) 기반 인덱스를 사용하여 스펠링 오류가 있는 텍스트나 부분 일치 텍스트를 빠르게 검색할 수 있게 해줍니다.
      • hstore: 키-값 쌍을 단일 컬럼에 저장할 수 있는 데이터 타입입니다. JSONB와 유사하지만, 더 단순한 구조의 비정형 데이터를 저장할 때 유용합니다.
      • pgvector: 최근 AI 애플리케이션에서 사용되는 벡터 임베딩을 저장하고, 유클리드 거리, 코사인 유사도 등을 기반으로 유사한 벡터를 빠르게 검색할 수 있게 해줍니다. 이를 통해 DB 내부에서 추천 시스템, 시맨틱 검색 등을 구현할 수 있습니다.

2. NoSQL급의 JSON 지원 (JSONB)

PostgreSQL의 JSONB 타입은 관계형 데이터베이스의 강점과 NoSQL 데이터베이스의 유연성을 결합한 매우 강력한 기능입니다.

  • 설명: JSONB는 JSON 데이터를 텍스트 그대로 저장하는 JSON 타입과 달리, 바이너리 형태로 파싱하여 저장합니다. 이 바이너리 형식은 JSON 데이터를 검색하거나 조작할 때 더 효율적입니다.
  • 장점:
    • 유연한 스키마: 테이블의 특정 컬럼에 JSONB를 사용하여 고정된 스키마 없이 다양한 속성을 저장할 수 있습니다. 이는 특히 새로운 데이터 속성이 자주 추가되거나, 속성들이 모든 레코드에 일관되지 않은 경우에 매우 유용합니다.
    • 강력한 쿼리 및 연산:
      • JSONB 데이터 내부의 특정 키에 접근하거나(>, >>), 경로를 따라 데이터를 추출하고(#>, #>>), 배열을 조작하고(jsonb_array_elements), 특정 키나 값이 존재하는지 확인할 수 있는(?, @>, ?&) 등 다양한 연산자를 제공합니다.
      • JSONB 데이터 내부의 특정 값에 대한 WHERE 절 조건을 사용하여 필터링할 수 있습니다.
    • 인덱싱 가능: JSONB 컬럼 전체에 GIN(Generalized Inverted Index) 인덱스를 걸거나, 특정 JSON 경로(예: (data->'user'->'id'))에 인덱스를 걸 수 있습니다. 이는 JSONB 데이터에 대한 검색 성능을 획기적으로 향상시킵니다.
    • 관계형 데이터와의 결합: 정형화된 관계형 데이터와 비정형 JSON 데이터를 한 쿼리에서 조인하고 분석할 수 있어, 복잡한 데이터 모델링을 단순화하고 애플리케이션 계층의 로직 부담을 줄일 수 있습니다.
  • 예시:
    • 전자상거래 플랫폼에서 products 테이블에 details라는 JSONB 컬럼을 만들어 상품별로 다른 추가 속성(예: 의류의 color, size, 전자기기의 processor, RAM)을 저장할 수 있습니다.
    • 사용자 프로필 테이블에 user_preferences라는 JSONB 컬럼을 두어 사용자의 다양한 설정(예: theme, notifications.email, notifications.sms)을 저장하고, 이 데이터를 쉽게 쿼리하고 업데이트할 수 있습니다.
    • 로그 데이터를 저장할 때, event_data 컬럼에 JSONB를 사용하여 다양한 형태의 로그 이벤트를 일관된 테이블 구조로 저장하면서도 각 이벤트의 세부 속성을 유연하게 관리할 수 있습니다.

3. 고도의 동시성 제어 (MVCC)

PostgreSQL은 **MVCC(Multi-Version Concurrency Control, 다중 버전 동시성 제어)**를 통해 높은 동시성을 제공하며, 특히 읽기 작업이 쓰기 작업을 방해하지 않는다는 큰 장점을 가집니다.

  • 설명: 데이터베이스에 저장된 데이터의 여러 버전을 동시에 유지 관리하여, 어떤 트랜잭션이 데이터를 수정하는 동안에도 다른 트랜잭션이 그 데이터의 이전 버전을 읽을 수 있도록 합니다. 각 트랜잭션은 자신이 시작된 시점의 '데이터 스냅샷'을 보게 됩니다.
  • 장점:
    • 읽기 작업 시 잠금(Lock) 없음: 데이터 읽기 작업(SELECT)은 데이터를 수정하는 다른 트랜잭션에 의해 잠기지 않습니다. 이로 인해 읽기 작업이 쓰기 작업을 차단하지 않고, 쓰기 작업도 읽기 작업을 차단하지 않습니다. (MySQL의 InnoDB 등 다른 DB도 MVCC를 사용함. READ COMMITTED나 REPEATABLE READ와 같은 격리 수준을 제공하며 innoDB도 select 문이 update, delete와 같은 쓰기 작업을 차단히지 않도록 여러 버전의 데이터를 유지한다.)
    • 높은 동시성: 동시에 많은 사용자가 데이터를 읽고 쓰는 환경에서, Lock 경합으로 인한 성능 저하 없이 높은 처리량을 유지할 수 있습니다. 웹 서비스처럼 읽기 요청이 많은 환경에 특히 유리합니다.
    • 트랜잭션 격리: 트랜잭션 간의 간섭을 최소화하여 데이터의 일관성과 정확성을 보장합니다. 특히 SERIALIZABLE과 같은 높은 격리 수준에서도 성능 손실이 상대적으로 적습니다.
    • 긴 쿼리의 안정성: 분석 쿼리처럼 실행 시간이 긴 SELECT 문이 실행되는 동안에도, 다른 트랜잭션들이 데이터를 자유롭게 수정할 수 있으며, SELECT 문은 자신이 시작된 시점의 일관된 데이터를 보장받습니다.
  • MySQL과의 차이점
    1. Write Lock 방식
      • Postgresql : update나 delete 시 일반적으로 해당 행에 대한 Exclusive Lock을 걸지만, 이는 다른 읽기 트랜잭션에는 영향을 주지 않는다. (오래된 버전을 읽게 함) 또한 update는 새 버전을 만들고 기존 버전을 ‘사용 불가능’ 으로 표시하는 방식
      • MySQL : update나 delete 시 해당 행에 대한 Exclusive Lock을 걸며 Lock은 다른 쓰기 트랜잭션은 물론 경우에 따라 SELECT … FOR UPDATE 같은 특정 읽기 트랜잭션도 차단한다. Lcok 경합이 더 빈번하게 발생
    2. Vacuum 프로세스
      • Postgresql : MVCC의 부산물로 dead tuples(즉 이전 버전의 데이터)이 발생한다. Postgresql은 이 죽은 튜플들을 주기적으로 정리하는 VACUUM이라는 별도의 프로세스가 필요하다. VACUUM은 시스템 오버헤드를 유발할 수 있으며, 이 과정이 적절히 관리 되지 않으면 테이블 파일 크기가 커지거나 성능 저하가 발생할 수 있다.
      • MySQL : InnoDB는 PURGE 스레드를 통해 백그라운드에서 자동으로 이전 버전의 데이터를 정리한다. 사용자(DBA)가 직접 개입해야 하는 VACUUM 같은 명시적인 작업은 없다.
    3. 트랜잭션 격리 수준 구현의 강점
      • Postgresql : SERIALIZABLE 격리 수준에서 발생하는 직렬화 실패(Serialization Failure)를 탐지하고 사용자에게 재시도를 요구하는 방식으로 구현되어, 가장 높은 수준의 트랜잭션 일관성을 강력하게 보장한다.
      • MySQL : InnoDB는 REPEATABLE READ가 기본 격리 수준이며, 이 수준에서도 ‘팬텀 리드’ 문제가 발생하지 않도록 MVCC를 호가장하여 구현한다. SERIALIZABLE도 지원하지만 실제 애플리케이션에서는 겨의 사용되지 않는다.
    4. 결론 : Postgresql의 MVCC는 읽기와 쓰기가 서로 영향을 미치지 않도록 하는데 더 순수하고 강력한 접근 방식을 가진다. 다만 이로 인해 VACUUM이라는 관리 오버헤드가 발생한다는 트레이드오프가 있다. InnoDB는 이를 좀 더 자동화하고 간소화했지만, 특정 동시성 시나리오에서 Lock 경합이 더 발생할 수 있다.
  • 예시:
    • 사용자가 웹사이트에서 게시물을 읽는 동안(SELECT), 동시에 다른 사용자가 해당 게시물을 수정(UPDATE)하더라도 서로의 작업에 영향을 주지 않고 원활하게 서비스가 제공됩니다.
    • 데이터 분석가가 대용량 보고서 쿼리를 실행하는 동안에도, 실시간으로 들어오는 거래 데이터가 문제없이 DB에 기록됩니다.

4. 복잡한 쿼리 및 분석 성능

PostgreSQL은 단순한 CRUD 작업을 넘어, 복잡한 데이터 분석 및 보고서 생성 쿼리에서 뛰어난 성능을 발휘합니다.

  • 똑똑한 쿼리 최적화기(Query Optimizer):
    • 설명: 사용자가 작성한 SQL 쿼리를 실행하기 전에, 데이터베이스는 쿼리 실행 계획을 수립합니다. PostgreSQL의 옵티마이저는 JOIN 순서, 인덱스 사용 여부, 임시 테이블 생성 여부 등 수많은 가능성 중에서 가장 효율적인 실행 경로를 찾아내는 데 매우 정교합니다. 통계 정보를 활용하여 데이터 분포를 이해하고 최적의 계획을 세웁니다.
    • 장점: 개발자가 쿼리를 작성할 때 성능 최적화에 대한 부담을 덜고, 더 선언적인 방식으로 쿼리를 작성할 수 있도록 돕습니다. 복잡한 쿼리일수록 옵티마이저의 역할이 중요해집니다.
  • 다양한 인덱스 타입:
    • 설명: PostgreSQL은 B-Tree(가장 일반적), Hash, GiST(Generalized Search Tree), SP-GiST, GIN(Generalized Inverted Index), BRIN(Block Range Index) 등 매우 다양한 인덱스 타입을 제공합니다. 각 인덱스 타입은 특정 데이터 타입이나 쿼리 패턴에 최적화되어 있습니다.
    • 장점:
      • 쿼리 효율 극대화: 텍스트 검색(GIN), 지리 공간 검색(GiST), 대용량 시계열 데이터 검색(BRIN) 등 특정 목적에 맞는 인덱스를 선택하여 쿼리 성능을 비약적으로 향상시킬 수 있습니다.
      • 유연성: 다양한 데이터 형태(JSONB, 배열, 텍스트 등)에 대해 효율적인 인덱싱을 지원합니다.
    • 예시: JSONB 컬럼에 GIN 인덱스를 걸면, JSONB 내부의 특정 키나 값에 대한 검색(WHERE data @> '{"status": "completed"}')이 매우 빨라집니다.
  • 병렬 쿼리(Parallel Query):
    • 설명: PostgreSQL은 하나의 복잡한 쿼리(예: 대용량 테이블 스캔, JOIN, 집계 함수 등)를 여러 개의 독립적인 태스크로 분할하여 여러 CPU 코어에서 병렬로 실행할 수 있습니다.
    • 장점: 멀티코어 CPU 환경에서 대용량 데이터에 대한 분석 쿼리나 보고서 생성 쿼리의 실행 시간을 획기적으로 단축시킵니다.
    • 예시: 수백만 건의 트랜잭션 데이터에 대해 GROUP BY와 SUM 연산을 수행하는 쿼리가 있다면, 병렬 쿼리 기능을 통해 훨씬 빠르게 결과를 얻을 수 있습니다.
  • 고급 분석 함수 (Window Functions, CTEs 등):
    • 설명: WINDOW FUNCTIONS (예: ROW_NUMBER(), LAG(), LEAD(), RANK()), CTE (Common Table Expressions) (WITH 절), MATERIALIZED VIEWS 등 복잡한 데이터 분석과 보고서 작성을 위한 강력한 SQL 기능을 폭넓게 지원합니다.
    • 장점: 애플리케이션 계층에서 복잡한 로직을 구현하지 않고도 SQL 쿼리만으로 복잡한 통계, 순위, 이동 평균 등을 계산할 수 있습니다.
  • MySQL과의 차이점
    1. 쿼리 옵티마이저의 정교함
      • Postgresql : 일반적으로 Postgresql의 옵티마이저가 더욱 정교하고 복잡한 쿼리에 대해 최적의 실행 계획을 찾아내는 능력이 뛰어나다. 특히 서브쿼리, 복잡한 조인, 윈도우 함수 등 다양한 고급 SQL 기능을 사용할 때 빛을 발한다.
      • Mysql innodb : 많이 발전햇지만, 특정 복잡한 쿼리나 최적화 힌트가 필요한 상황에서 postgresql보다 덜 효율적인 계획을 세우는 경우가 있다.
    2. 인덱스 타입의 다양성과 유연성
      • PostgreSQL: B-Tree 외에 GIN, GiST, SP-GiST, BRIN 등 다양한 특수 목적 인덱스를 제공합니다. 이는 텍스트 검색(pg_trgm), 지리 공간(PostGIS), JSONB 데이터 내부 검색(JSONB + GIN) 등 특정 데이터 형태와 쿼리 패턴에 대한 성능을 극대화할 수 있습니다.
      • MySQL InnoDB: 주로 B-Tree 인덱스를 기반으로 하며, 전체 텍스트 검색을 위한 FULLTEXT 인덱스나 공간 검색을 위한 R-Tree 인덱스 등을 지원하지만, PostgreSQL의 확장성과 유연성에는 미치지 못합니다.
    3. 병렬 쿼리
      • PostgreSQL: 9.6 버전부터 SELECT, CREATE TABLE AS, CREATE INDEX 등 다양한 작업에서 쿼리 자체를 병렬로 실행하는 기능을 적극적으로 활용합니다.
      • MySQL InnoDB: 8.0부터 일부 병렬 쿼리 기능을 도입했지만, PostgreSQL만큼 광범위하고 깊이 있게 구현되지는 않았습니다. 특히 GROUP BY, ORDER BY 같은 작업의 병렬 처리에서는 PostgreSQL이 강점을 보입니다.

5. 데이터 무결성과 표준 준수

PostgreSQL은 데이터의 신뢰성과 장기적인 유지보수성을 매우 중요하게 생각하는 DB입니다.

  • 엄격한 ACID 준수:
    • 설명: PostgreSQL은 트랜잭션의 4가지 속성인 **원자성(Atomicity), 일관성(Consistency), 격리성(Isolation), 영속성(Durability)**을 매우 엄격하게 준수합니다. 이는 데이터가 손실되거나 손상될 위험 없이 항상 정확하고 신뢰할 수 있음을 의미합니다.
    • 장점:
      • 데이터 신뢰성: 금융 시스템, 의료 기록, 재고 관리 등 데이터의 정확성이 생명인 애플리케이션에 필수적입니다.
      • 예상 가능한 동작: 트랜잭션이 어떤 상황에서도 예측 가능한 방식으로 작동하므로 개발자가 데이터 관련 오류를 방지하기 용이합니다.
  • SQL 표준 준수:
    • 설명: PostgreSQL은 ANSI SQL 표준을 가장 잘 따르는 관계형 데이터베이스 중 하나입니다. 대부분의 표준 SQL 문법과 기능이 PostgreSQL에서 지원됩니다.
    • 장점:
      • 개발자 학습 곡선: 표준 SQL에 익숙한 개발자는 PostgreSQL에 쉽게 적응할 수 있습니다.
      • 쿼리 이식성: PostgreSQL에서 작성된 쿼리는 다른 표준 SQL 데이터베이스(예: Oracle, SQL Server)로 이식하기가 비교적 쉽습니다. 이는 장기적인 유지보수와 기술 전환에 유리합니다.
      • 문서 및 자료의 풍부함: 표준을 따르므로 관련 문서나 커뮤니티 자료를 찾기 용이합니다.
  • 강력한 외래 키(Foreign Key) 제약:
    • 설명: 테이블 간의 관계를 정의하는 외래 키 제약을 강력하게 지원하고 검증합니다.
    • 장점:
      • 참조 무결성: 참조하는 테이블의 데이터가 삭제되거나 변경될 때 참조되는 테이블의 데이터도 함께 일관되게 유지되도록 보장합니다(예: ON DELETE CASCADE, ON UPDATE RESTRICT).
      • 데이터 일관성: 애플리케이션 수준에서 복잡한 참조 무결성 로직을 구현할 필요 없이 DB가 이를 자동으로 관리하여 데이터의 일관성을 유지합니다.
  • MySQL과의 차이점
    • ACID 준수의 엄격함:
      • PostgreSQL: 전통적으로 ACID 속성을 매우 엄격하게, 보수적으로 준수하는 것으로 유명합니다. 특히 내구성(Durability) 측면에서 fsync와 같은 디스크 동기화 작업을 철저히 처리하여 데이터 손실 위험을 최소화합니다.
      • MySQL InnoDB: MySQL 5.x 버전대에서는 기본 설정(예: innodb_flush_log_at_trx_commit = 0)에서 성능을 위해 ACID 준수(특히 내구성)를 일부 희생하는 경우가 있었습니다. 최신 버전에서는 많이 개선되었지만, 기본 철학에서 PostgreSQL이 좀 더 '안전'에 중점을 둡니다.
    • SQL 표준 준수 및 기능 구현 깊이:
      • PostgreSQL: SQL 표준을 가장 잘 따르는 오픈소스 DB 중 하나입니다. 거의 모든 표준 SQL 기능을 지원하며, 이를 일관되고 예측 가능한 방식으로 구현합니다.
      • MySQL InnoDB: SQL 표준을 따르지만, 특정 기능(예: CHECK 제약 조건 - 8.0 이전에는 파싱만 하고 실제 검사 안 함, 특정 JOIN 문법)에서 표준과 다르거나 제한적인 구현이 있었습니다. 또한 PostgreSQL이 제공하는 WITH RECURSIVE, MATERIALIZED VIEWS 등 고급 표준 SQL 기능은 MySQL에서 뒤늦게 추가되거나 기능적 제한이 있는 경우가 많습니다.
    • 데이터 타입의 엄격함:
      • PostgreSQL: 데이터 타입에 대한 검증과 형 변환이 더 엄격합니다. 명시적인 형 변환을 요구하는 경우가 많습니다.
      • MySQL InnoDB: 비교적 느슨한 타입 검사와 자동 형 변환을 제공합니다. 이는 때로는 개발 편의성을 높이지만, 예상치 못한 데이터 타입 변환으로 인한 오류나 성능 저하를 유발할 수 있습니다.
    • CHECK 제약 조건:
      • PostgreSQL: CHECK 제약 조건을 완벽하게 지원하며, 이를 통해 컬럼 값에 대한 복잡한 규칙을 DB 수준에서 강제할 수 있습니다.
      • MySQL InnoDB: 8.0 이전 버전에서는 CHECK 제약 조건을 파싱은 하지만 실제로 검사하지 않아 기능하지 않았습니다. 8.0부터는 실제로 동작합니다.

dml 쿼리에 대한 고찰

두 DB 모두 쓰기 작업(DML)에 Lock을 걸어 다른 쓰기 작업을 차단하는 것은 동일합니다. 하지만 PostgreSQL이 더 유연하다고 평가받는 근본적인 이유는 데이터를 수정하는 방식(MVCC 구현 방식)의 차이에 있습니다. 핵심은 PostgreSQL의 UPDATE가 데이터를 덮어쓰지 않고 새로운 행 버전을 생성한다는 점입니다.

1. PostgreSQL: '새 행 생성' 방식의 MVCC (Tuple-Based)

PostgreSQL은 데이터의 모든 버전을 테이블(heap) 내에 유지합니다.

작업 동작 방식 락(Lock)의 성격 및 기간

UPDATE 1. 기존 행을 '사용 불가'로 표시 (DELETE). 2. 새로운 행을 테이블의 다른 위치에 삽입 (INSERT). 데이터 수정 작업 자체에 걸리는 Lock은 매우 짧습니다. 기존 행을 '사용 불가'로 표시하고 새 행을 삽입하는 트랜잭션 ID 관련 락만 빠르게 획득했다가 해제됩니다.
SELECT Lock을 전혀 신경 쓰지 않고 쿼리가 시작된 시점의 이전 버전을 읽습니다. Lock 경합(Contention)이 발생할 일이 없습니다.
결론 읽기-쓰기 간에 Lock 경합이 없습니다. 쓰기-쓰기 간의 Lock 경합은 존재하지만, 데이터 변경 작업이 **논리적인 '추가'**에 가까워 Lock이 필요한 기간이 최소화됩니다.  

2. MySQL InnoDB: '제자리 수정' 방식의 MVCC (Undo Log-Based)

InnoDB는 데이터를 물리적으로 제자리에서 수정하고, 롤백을 위해 이전 데이터를 Undo Log라는 별도의 공간에 기록합니다.

작업 동작 방식 락(Lock)의 성격 및 기간

UPDATE 기존 데이터를 물리적으로 덮어쓰기 위해 해당 행에 **배타적 Lock (X-Lock)**을 겁니다. 데이터 수정 작업이 완료될 때까지 Lock을 유지해야 합니다.
SELECT Lock 없이 현재 데이터를 읽지만, 필요하면 Undo Log를 참조하여 이전 버전의 데이터를 재구성해 읽습니다. Lock 경합이 발생하지 않습니다.
SELECT ... FOR UPDATE Lock을 획득해야 하는 작업이므로, 만약 해당 행에 이미 UPDATE나 DELETE가 진행 중이라면 X-Lock이 해제될 때까지 반드시 기다려야 합니다. Lock 경합이 발생합니다.

3. PostgreSQL이 더 유연하다고 평가받는 이유

PostgreSQL의 장점은 Lock 경합이 발생할 수 있는 시간 창(Window)을 최소화하는 데 있습니다.

  1. Lock Duration (락 유지 기간 최소화):PostgreSQL: UPDATE 시 새로운 행을 만드는 것은 매우 빠른 작업입니다. Lock은 이 짧은 **'행을 무효화하고 새로운 행을 삽입하는 시점'**에만 집중됩니다. 따라서 다른 쓰기 트랜잭션이 Lock 해제를 기다려야 하는 시간이 매우 짧습니다. ◦ InnoDB: 데이터를 물리적으로 수정하는 시간 동안 Lock을 유지해야 하므로, 복잡한 로우일수록 Lock 유지 시간이 길어지고 Lock 경합 가능성도 높아집니다.
  2. Lock Scope (락 범위의 단순성): ◦ PostgreSQL은 UPDATE 시 Lock이 필요한 대상이 데이터 자체보다는 트랜잭션 ID 영역에 가깝기 때문에, Lock의 복잡성이 줄어듭니다.
  3. 관리 오버헤드의 트레이드오프: ◦ PostgreSQL은 Lock 경합을 줄이는 대신, 남겨진 '죽은 튜플'을 정리하는 **VACUUM**이라는 별도의 청소 프로세스가 필요하다는 관리적 오버헤드가 있습니다. ◦ MySQL InnoDB는 이 청소 작업을 자동으로 처리하지만, Lock 경합의 가능성이 더 높아지는 트레이드오프를 가집니다. 결론적으로, 두 DB 모두 SELECT ... FOR UPDATE 같은 명시적인 Locking Read에서는 Lock 경합을 피할 수 없습니다. 하지만 일반적인 UPDATE나 DELETE 작업에서 PostgreSQL은 MVCC 구현 방식 덕분에 Lock을 잡고 있는 시간을 최소화하여 쓰기-쓰기 및 Lock-획득 읽기(SELECT FOR UPDATE) 간의 동시성 경합을 InnoDB보다 더 효과적으로 줄일 수 있습니다.
반응형

'CS > DataBase' 카테고리의 다른 글

격리수준이란  (0) 2026.03.12
redo log(mysql 8.0)  (0) 2025.09.16
[DB] Prepared Statement란?  (0) 2025.06.10
[DataBase] 인덱스란?  (1) 2025.03.26
[DB] MVCC(다중 버전 동시성 제어)  (0) 2025.03.26