본문으로 건너뛰기

1.2 인스턴스와 클러스터

PostgreSQL의 인스턴스(instance) 한 개는 postmaster 프로세스 한 개 + 데이터 디렉토리(PGDATA) 한 개의 조합입니다. PostgreSQL 공식 문서는 이 단위를 데이터베이스 클러스터(database cluster)라고 부릅니다. 한 클러스터 안에는 여러 데이터베이스가 들어가지만, 클라이언트 연결은 항상 그 중 하나의 데이터베이스로만 들어갑니다.

운영자가 자주 혼동하는 지점은 "클러스터" 단어입니다. PostgreSQL의 "데이터베이스 클러스터"는 분산 시스템에서 말하는 "여러 노드로 묶인 클러스터"와는 다른 개념입니다.

PostgreSQL 인스턴스와 연결 경계

계층 관계​

공식 문서가 정의하는 전체 계층은 cluster → database → schema → table(또는 다른 객체)입니다. 이 네 레벨이 PostgreSQL의 네임스페이스 골격입니다.

레벨단위메모
Clusterpostmaster 1개가 관리하는 데이터베이스 묶음initdb로 생성, 파일시스템상 PGDATA 디렉토리 1개
Database같은 클러스터 안에서 격리된 단위CREATE DATABASE, 클러스터 안에서 OID로 식별
Schema데이터베이스 안의 네임스페이스CREATE SCHEMA, 이름 공간·권한 분리
객체테이블·인덱스·시퀀스·뷰·함수 등항상 스키마 안에 속함

한 연결 = 한 데이터베이스​

클라이언트는 접속할 때 반드시 데이터베이스 하나를 골라야 합니다.

psql -h localhost -U postgres -d app_main

같은 클러스터 안에 있어도 다른 데이터베이스의 테이블을 직접 join하는 건 불가능합니다. 이건 PostgreSQL의 의도된 격리 모델입니다.

노트

공식 문서 인용: "When connecting to the database server, a client must specify the database name in its connection request. It is not possible to access more than one database per connection."

다른 데이터베이스에 접근하려면 두 가지 우회 경로가 있습니다.

우회방법비고
postgres_fdw다른 DB(같은 클러스터든 다른 클러스터든)를 외부 테이블로 매핑표준 SQL/MED, Part XVI 참고
dblink 확장함수 호출로 다른 DB 쿼리원격 쿼리 결과를 레코드 집합으로 받아 로컬에서 조인. push-down 없음

자동 생성되는 세 데이터베이스​

initdb가 클러스터를 초기화하면 데이터베이스 세 개가 미리 들어갑니다.

데이터베이스역할
postgres관리용·기본 접속 데이터베이스. 유틸리티·서드파티 도구가 디폴트로 쓴다
template1새 데이터베이스(CREATE DATABASE foo) 생성 시 복제되는 템플릿. 여기 객체를 만들어 두면 이후 만든 모든 DB에 자동으로 들어간다
template0수정하지 않는 원본(pristine) 템플릿. 다른 인코딩/로케일 DB 생성이나 pg_restore 대상 DB 생성에 사용

데이터 디렉토리 (PGDATA)​

클러스터 한 개는 파일시스템상 하나의 디렉토리입니다. 이 디렉토리를 PGDATA라 부르며, 환경 변수 PGDATA 또는 pg_ctl -D 옵션으로 위치를 지정합니다.

흔히 쓰이는 경로:

OS·배포기본 PGDATA
RHEL/Rocky (PGDG yum)/var/lib/pgsql/<version>/data
Debian/Ubuntu (PGDG apt)/var/lib/postgresql/<version>/<cluster>
Homebrew macOS/opt/homebrew/var/postgresql@<version>
소스 빌드 관례/usr/local/pgsql/data
공식 Docker 이미지/var/lib/postgresql/data

PGDATA 내부 구조​

$PGDATA/
├── PG_VERSION # 메이저 버전 (예: "17")
├── postgresql.conf # 주 설정
├── pg_hba.conf # 클라이언트 인증
├── pg_ident.conf # OS 사용자 ↔ DB 사용자 매핑
├── postgresql.auto.conf # ALTER SYSTEM이 쓰는 설정
├── postmaster.pid # 실행 중인 postmaster PID·소켓·포트 정보
├── postmaster.opts # 마지막 기동 명령행 옵션
├── base/ # 데이터베이스별 데이터 (DB OID로 디렉토리)
│ ├── 1/ # template1
│ ├── 4/ # template0
│ ├── 5/ # postgres
│ └── 16384/ # 사용자 DB (CREATE DATABASE 결과)
├── global/ # 클러스터 전역 카탈로그 (pg_database 등)
├── pg_wal/ # WAL 세그먼트 (16MB 단위 파일)
├── pg_tblspc/ # tablespace 심볼릭 링크
├── pg_xact/ # 트랜잭션 커밋 상태 (CLOG)
├── pg_multixact/ # 멀티트랜잭션 (공유 row lock)
├── pg_subtrans/ # 서브트랜잭션 상태
├── pg_commit_ts/ # 커밋 타임스탬프
├── pg_twophase/ # 2PC prepared transaction 상태
├── pg_replslot/ # 복제 슬롯
├── pg_logical/ # 로지컬 디코딩 상태
├── pg_serial/ # SERIALIZABLE 트랜잭션 정보
├── pg_notify/ # LISTEN/NOTIFY 큐
├── pg_snapshots/ # 내보낸 스냅샷
├── pg_stat/ # 통계 시스템 영구 파일
├── pg_stat_tmp/ # 통계 시스템 임시 파일
└── pg_dynshmem/ # 동적 공유 메모리 메타데이터

각 항목의 역할을 묶어서 봅니다.

그룹디렉토리·파일용도
메타PG_VERSION, postmaster.pid, postmaster.opts버전·기동 상태 표시
설정postgresql.conf, pg_hba.conf, pg_ident.conf, postgresql.auto.conf서버·인증·매핑·동적 설정
실제 데이터base/, global/, pg_tblspc/사용자 데이터 + 전역 카탈로그 + 외부 tablespace 링크
WALpg_wal/트랜잭션 로그 (16MB 세그먼트, archive·replication의 원천)
트랜잭션 상태pg_xact/, pg_multixact/, pg_subtrans/, pg_commit_ts/, pg_twophase/커밋·잠금·서브·2PC 상태
복제·로지컬pg_replslot/, pg_logical/, pg_serial/replication slot·logical decoding·SSI
런타임pg_notify/, pg_snapshots/, pg_stat/, pg_stat_tmp/, pg_dynshmem/알림·스냅샷·통계·동적 공유 메모리
경고

PGDATA 안의 파일은 절대 수동 편집하지 않습니다. 특히 pg_wal/의 WAL 세그먼트를 임의 삭제하면 클러스터가 부팅 불가 상태가 됩니다. 백업·정리는 pg_archivecleanup 등 공식 도구를 거쳐야 합니다.

클러스터 생성: initdb​

빈 디렉토리에 initdb를 실행하면 위의 골격이 만들어집니다.

# 일반적인 형태 (RHEL 계열 패키지가 깔린 경우)
sudo -u postgres /usr/pgsql-17/bin/initdb \
-D /var/lib/pgsql/17/data \
--encoding=UTF8 \
--locale=C.UTF-8 \
--data-checksums

자주 쓰는 옵션:

옵션의미
-D <dir>PGDATA 위치. 환경 변수 PGDATA로 대체 가능
--encoding=UTF8클러스터 기본 인코딩
--locale=C.UTF-8정렬·문자 분류 로케일. C 로케일은 ASCII 비교, 빠름
--data-checksums데이터 페이지 체크섬 활성 (온라인 변경 불가, 오프라인 pg_checksums 필요, 운영 권장)
-U <user>슈퍼유저 이름 (기본 postgres)
--wal-segsize=<MB>WAL 세그먼트 크기 변경 (기본 16MB, 일부 워크로드에서 64MB·128MB 고려)

initdb는 다음을 수행합니다.

  1. PGDATA 디렉토리 권한 0700(또는 0750)으로 설정
  2. PG_VERSION 작성
  3. 시스템 카탈로그 + template0·template1·postgres 생성
  4. postgresql.conf·pg_hba.conf 기본 파일 작성
노트

initdb는 디렉토리가 비어 있어야 실행됩니다. 이미 파일이 있으면 "directory ... is not empty" 오류로 거부합니다 — 기존 클러스터를 실수로 덮어쓰지 못하게 막는 안전장치입니다.

한 호스트, 여러 클러스터​

PostgreSQL은 한 호스트에 클러스터를 여러 개 띄우는 걸 정식으로 지원합니다. 각 클러스터는:

  • 별도 PGDATA
  • 별도 postmaster 프로세스
  • 별도 TCP 포트 (postgresql.conf의 port 파라미터)
  • 별도 Unix 도메인 소켓 디렉토리
호스트 1대
├── 클러스터 A
│ ├── PGDATA: /var/lib/pgsql/17/data
│ ├── postmaster (PID 12345)
│ └── port 5432
└── 클러스터 B
├── PGDATA: /data/pg17-staging
├── postmaster (PID 12678)
└── port 5433

Debian/Ubuntu는 pg_ctlcluster·pg_lsclusters 같은 클러스터 관리 도구를 기본 제공해, 한 호스트에 여러 클러스터를 일상적으로 운영하는 패턴을 전제합니다. RHEL 계열은 versioned 패키지(postgresql17-server)가 버전별로만 충돌을 피하므로, 같은 메이저로 여러 클러스터를 띄우려면 systemd 유닛을 복제해서 씁니다.

정리​

  • PostgreSQL 인스턴스 = postmaster 1개 + PGDATA 1개
  • 공식 명칭은 "데이터베이스 클러스터" — 분산 클러스터 아님
  • 계층: cluster → database → schema → table/index/…
  • 한 연결은 한 데이터베이스만 봅니다. 다른 DB로 가려면 새 연결 또는 FDW/dblink
  • PGDATA 안에는 설정·실제 데이터·WAL·트랜잭션 상태·통계가 모두 모입니다. 수동 편집 금지
  • initdb로 클러스터 골격을 만듭니다. --data-checksums 활성 권장 (온라인 변경 불가, 오프라인 pg_checksums 필요)
  • 한 호스트에 클러스터 여러 개 가능 — 포트·소켓·PGDATA로 격리