1P by GN⁺ 17일전 | ★ favorite | 댓글 1개
  • PostgreSQL 18은 파일 복제 전략(FILE_COPY)파일 시스템 클론 기능을 결합해 데이터베이스를 거의 즉시 복제할 수 있음
  • 새로운 설정값 file_copy_method = clone 을 사용하면 XFS, ZFS, APFS 등 현대적 파일시스템의 복제 기능(FICLONE) 을 활용 가능
  • 벤치마크 결과, 6GB 데이터베이스 복제 시 기존 WAL_LOG 방식은 약 67초, 클론 방식은 0.2초 수준으로 단축됨
  • 복제된 데이터베이스는 초기에는 동일한 물리 블록을 공유하지만, 쓰기 작업 시 copy-on-write로 분리됨
  • 단, 활성 연결이 없는 상태에서만 복제 가능하며, 단일 파일시스템 내에서만 작동하는 제약 존재

PostgreSQL의 템플릿 기반 복제 구조

  • PostgreSQL은 CREATE DATABASE dbname 명령 시 내부적으로 template1 데이터베이스를 복제해 새 데이터베이스를 생성
    • 이는 CREATE DATABASE dbname TEMPLATE template1 과 동일한 동작
  • template1 대신 다른 데이터베이스를 지정할 수 있어, 사용자 정의 템플릿을 활용한 복제 가능
  • PostgreSQL 18에서는 이 템플릿 시스템을 즉시 복제 가능한 구조로 확장

CREATE DATABASE ... STRATEGY

  • PostgreSQL 15부터 CREATE DATABASE ... STRATEGY 매개변수가 도입되어 복제 방식 선택 가능
    • 기본값은 WAL_LOG로, Write-Ahead Log를 통한 블록 단위 복제 수행
    • 이 방식은 I/O 부하를 줄이고 동시성 지원을 개선하지만, 대용량 복제 시 속도가 느림
  • STRATEGY=FILE_COPY를 지정하면 기존 파일 복사 방식으로 되돌릴 수 있으며, PostgreSQL 18에서는 이를 기반으로 새로운 복제 옵션 추가

FILE_COPY와 file_copy_method

  • PostgreSQL 18의 file_copy_method 설정은 운영체제 수준의 파일 복제 방식을 제어
    • 기본값은 copy이며, 모든 바이트를 읽고 새 위치에 기록
    • clone으로 변경하면 파일시스템의 클론 기능(FICLONE) 을 사용해 즉시 복제 및 추가 공간 소모 없음
  • 지원 파일시스템: XFS, ZFS, APFS, FreeBSD ZFS
  • 설정 절차
    • 해당 파일시스템 위에 PostgreSQL 클러스터 구성
    • file_copy_method = clone 설정 후 재로드

벤치마크 결과

  • 약 6GB 크기의 테스트 데이터베이스(source_db) 생성 후 두 가지 방식 비교
    • WAL_LOG 방식: 67,000ms (약 67초)
    • FILE_COPY + clone 방식: 212ms
  • 동일한 데이터 크기에서 약 300배 이상 속도 향상 확인
  • 복제된 데이터베이스(fast_clone)는 추가 디스크 공간을 거의 사용하지 않음

복제된 데이터의 동작 원리

  • file_copy_method = clone 사용 시, 파일시스템 메타데이터만 복제되어 두 데이터베이스가 동일한 물리 블록을 공유
  • PostgreSQL이 보고하는 데이터베이스 크기는 논리적 크기(약 6GB)로 동일
  • 쓰기 작업 발생 시 copy-on-write(COW) 가 작동하여 해당 페이지가 분리됨
    • 수정된 행이 포함된 페이지
    • 새 튜플이 기록되는 페이지
    • 인덱스 페이지 및 FSM, visibility map 페이지 등
  • VACUUM 실행 시에도 추가적인 페이지 분리 발생

XFS에서의 공유 블록 검증

  • filefrag -v 명령으로 두 데이터베이스의 물리 블록 공유 여부 확인
    • 초기 상태에서는 모든 extents가 shared로 표시
    • 일부 행을 업데이트하면 첫 40블록(약 160KB)이 분리되어 서로 다른 물리 주소로 변경
    • 나머지 extents는 여전히 공유 상태 유지

주의사항 및 제약

  • 복제 시 원본 데이터베이스에 활성 연결이 없어야 함
    • 이는 PostgreSQL의 제약이며, 파일시스템 문제는 아님
    • 실서비스 환경에서는 별도의 템플릿 데이터베이스를 사용하는 것이 일반적
  • 단일 파일시스템 내에서만 복제 가능
    • 여러 테이블스페이스가 서로 다른 마운트 포인트에 있을 경우, 일반 복사로 대체됨
  • 클라우드 관리형 서비스(AWS RDS, Google Cloud SQL 등) 에서는 파일시스템 접근이 불가하므로 이 기능 사용 불가
    • 자체 VM이나 베어메탈 환경에서는 완전한 제어 가능

결론

  • PostgreSQL 18의 file_copy_method = clone 기능은 운영체제 수준의 클론 기능을 직접 활용
    대용량 데이터베이스 복제 시간을 극적으로 단축
  • 테스트, 개발, 학습 환경에서 즉시 복제 및 리셋 가능한 데이터베이스 워크플로우 구현 가능
  • 단, 활성 연결 제약과 파일시스템 단일성을 고려한 운영 설계 필요
Hacker News 의견들
  • 기다릴 수 없거나 PG18의 완전한 인스턴스 격리가 필요한 사람들을 위해, 나는 ZFS 스냅샷을 이용해 즉시 브랜칭하는 도구 Velo를 만들었음
    어떤 PostgreSQL 버전에서도 작동하며, 각 브랜치는 독립된 컨테이너와 포트를 가짐
    100GB DB 기준 약 2~5초면 생성 가능함
    PG18 방식과의 차이는, 단일 인스턴스를 공유하지 않고 완전한 서버 격리를 제공한다는 점임
    GitHub 링크

    • 다른 댓글에서 Claude Code 사용에 대한 불만이 있었지만, GitHub 페이지의 데모 영상을 보고 흥미롭게 느꼈음
    • 요즘 대부분의 소프트웨어가 AI 에이전트의 도움을 받아 작성되는데, 왜 불평이 나오는지 모르겠음. 접근 방식이 흥미로움
    • 나도 비슷한 걸 btrfs로 프로토타입 해보려던 참이었음
    • “너”라는 표현이 흥미롭다고 생각했는데, 표절했다는 말이 있어서 좀 놀랐음
  • 예전에 회사가 RDS로 마이그레이션할 때 비슷한 시스템을 직접 구축했음
    프로덕션 마이그레이션 중 자주 문제가 생겨서, 이를 방지하기 위해 다음 단계를 자동화했음

    1. RDS DB를 복제하거나 백업에서 새 인스턴스를 생성
    2. ARN으로부터 CNAME 또는 퍼블릭 IP 추출
    3. 앱의 DB 연결 설정에 반영
    4. 가짜 프로덕션 환경에서 마이그레이션 실행
      이 과정 덕분에 로컬이나 CI에서는 잡히지 않던 프로덕션 특유의 버그를 많이 잡을 수 있었음
      이후 간단한 Ruby 스크립트로 자동화했고, 아직도 그 스크립트를 사용 중이라고 들었음
    • 나도 그런 “데이터 특이성 때문에 프로덕션에서만 실패하는 마이그레이션” 버그를 정말 싫어함. 몇 번은 그 때문에 릴리스를 취소한 적도 있음
  • 템플릿 클로닝 전략이 설정 가능하다는 걸 이번에 처음 알았음
    나는 Neon을 이용해 실시간 통합 환경을 만들었고, 내 Golang 프로젝트 pgtestdb 에서는 각 테스트마다 완전한 스키마 마이그레이션이 적용된 Postgres DB를 생성함
    예전에 스타트업에서 btrfs로 즉시 스테이징 DB를 만드는 걸 본 적 있는데, 비슷한 아이디어가 반복 등장하는 게 흥미로움
    이런 빠른 복제와 테스트는 Postgres와 Sqlite의 큰 장점이며, Clickhouse나 MySQL에서도 가능했으면 좋겠음

  • 요즘 PostgreSQL이 거의 모든 SQL 용도를 커버하는 만능 DB가 된 것 같음
    게다가 무료
    이제 굳이 다른 SQL DB를 쓸 이유가 있을까 궁금함

    • Postgres는 훌륭하지만, MySQL은 마스터-마스터 복제가 더 쉽고, MongoDB는 지리적 분산과 샤딩이 간단함
      Clickhouse는 분석용으로 훨씬 빠르고, Cassandra 같은 DB는 쓰기 중심 워크로드에 유리함
      즉, 각 DB마다 여전히 강점이 있음
    • “모든 걸 잘한다”는 표현은 과장임
      데이터가 많아지면 성능 저하마이그레이션 문제가 생김
      내 경우, 기본 파티셔닝 성능이 떨어져서 직접 커스텀 파티션을 구현해야 했음
    • Postgres는 여전히 MVCC 구현 방식(copy-on-write)이 비효율적임
      이 선택이 부하가 커질 때 여러 부정적 영향을 줌
    • 예전에는 MySQL/InnoDB가 업데이트 중심 워크로드에서 더 나았음
      Uber의 블로그 글에서도 다뤘던 주제임
      그래도 클라우드 환경에서는 Postgres를 가장 신뢰함
    • Postgres에는 아직 Vitess 수준의 성숙한 대체재가 없음
      그래서 대규모 OLTP 배포에서는 여전히 MySQL이 주로 쓰임 (예: YouTube, Uber)
  • 불변 데이터 구조(HAMT) 를 이용하면 파일시스템 종류와 상관없이 즉시 클론이 가능한 DB를 만들 수 있음
    이론이라고 말했지만 실제로 구현해봤음
    왜 이런 HAMT 기반 DB가 더 많지 않은지 이해가 안 됨

    • 나는 ClickHouse의 작성자인데, ClickHouse도 불변 데이터 파트를 사용해 테이블 복제를 지원함
      관련 문서 링크
    • Datomic에도 이런 클로닝 기능이 내장되어 있는지 궁금함. 예전부터 써보고 싶었지만 실제 앱을 만들기엔 아직 마음의 준비가 안 됨
  • Postgres v15에서 WAL_LOG가 기본으로 바뀐 걸 몰랐음
    병렬 CI 테스트 환경에서는 FILE_COPY 전략으로 되돌리는 게 더 합리적임
    예전 프로젝트 integresql에 관련 이슈를 올렸음

  • 로컬에서 Postgres 기반 앱을 테스트하기 위한 간단한 GUI 도구 pgtt 를 만든 적 있음
    개발 환경 설정을 훨씬 단순화해줌

    • README만 봐서는 잘 모르겠는데, 템플릿을 스냅샷처럼 다루는 구조인지 궁금함
      SQL 마이그레이션 반복 작업에 도움이 될 것 같음
    • README에 GUI 스크린샷이 있으면 좋겠고, Docker 링크가 깨져 있음
  • 블로그의 다른 글들도 읽어봤는데 전반적으로 훌륭함
    특히 Postgres의 range 타입을 처음 알게 되었음

    • range 타입은 시간/날짜 구간 겹침 계산 같은 데서 정말 유용함
  • MariaDB에서도 이런 기능이 있는지 궁금함
    테스트마다 DB를 초기 상태로 되돌리는 게 느려서 고민 중임
    프로덕션에서 MariaDB를 쓰기 때문에 DB를 바꾸긴 어려움
    Postgres 쪽이 더 좋아 보이긴 함

    • 각 테스트를 트랜잭션 세션 안에서 실행하고, 끝날 때 롤백하면 빠르게 초기 상태로 복원 가능함
      이 방식이 꽤 효율적임
    • DB를 재시작해도 괜찮다면 LVM이나 btrfs 스냅샷을 파일시스템 레벨에서 사용하는 것도 방법임
  • AWS에서도 유사한 기능을 지원함
    Aurora 클론 문서

    • Aurora의 클론은 스토리지 레벨에서 copy-on-write로 동작하지만, 여전히 새 클러스터를 프로비저닝해야 해서 약 10분 정도 걸림
      통합 테스트용으로는 비현실적임
    • Aurora는 클러스터 단위 복제이고, 여기서 논의된 건 데이터베이스 단위 복제임