1.2 인스턴스와 클러스터
PostgreSQL의 인스턴스(instance) 한 개는 postmaster 프로세스 한 개 + 데이터 디렉토리(PGDATA) 한 개의 조합입니다. PostgreSQL 공식 문서는 이 단위를 데이터베이스 클러스터(database cluster)라고 부릅니다. 한 클러스터 안에는 여러 데이터베이스가 들어가지만, 클라이언트 연결은 항상 그 중 하나의 데이터베이스로만 들어갑니다.
운영자가 자주 혼동하는 지점은 “클러스터” 단어입니다. PostgreSQL의 “데이터베이스 클러스터"는 분산 시스템에서 말하는 “여러 노드로 묶인 클러스터"와는 다른 개념입니다. 본 절에서는 우선 단일 인스턴스 관점에서 클러스터·데이터베이스·스키마·객체의 계층 관계를 정리하고, PGDATA의 내부 구조를 봅니다.
계층 관계
flowchart TD
C["<b>Cluster</b><br/>postmaster 1개<br/>PGDATA 1개"]
C --> DB1["Database: <b>postgres</b><br/>(관리·기본)"]
C --> DB2["Database: <b>template1</b><br/>(새 DB 템플릿)"]
C --> DB3["Database: <b>template0</b><br/>(백업 템플릿)"]
C --> DB4["Database: <b>app_main</b>"]
DB4 --> S1["Schema: public"]
DB4 --> S2["Schema: billing"]
S1 --> T1["Table · Index · Sequence …"]
S2 --> T2["Table · Index · Sequence …"]
classDef cluster fill:#ede9fe,stroke:#6d28d9,color:#3b0764,stroke-width:2px
classDef db fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef sch fill:#d1fae5,stroke:#047857,color:#064e3b
classDef obj fill:#fef3c7,stroke:#b45309,color:#78350f
class C cluster
class DB1,DB2,DB3,DB4 db
class S1,S2 sch
class T1,T2 obj
공식 문서가 정의하는 전체 계층은 cluster → database → schema → table(또는 다른 객체) 다. 이 네 레벨이 PostgreSQL의 네임스페이스 골격입니다.
| 레벨 | 단위 | 메모 |
|---|---|---|
| Cluster | postmaster 1개가 관리하는 데이터베이스 묶음 | initdb로 생성, 파일시스템상 PGDATA 디렉토리 1개 |
| Database | 같은 클러스터 안에서 격리된 단위 | CREATE DATABASE, 클러스터 안 PostgreSQL OID로 식별 |
| Schema | 데이터베이스 안의 네임스페이스 | CREATE SCHEMA, 이름 공간·권한 분리 |
| 객체 | 테이블·인덱스·시퀀스·뷰·함수 등 | 항상 스키마 안에 속함 |
한 연결 = 한 데이터베이스
클라이언트는 접속할 때 반드시 데이터베이스 하나를 골라야 합니다.
psql -h localhost -U postgres -d app_main같은 클러스터 안에 있어도 다른 데이터베이스의 테이블을 직접 join하는 건 불가능합니다. 이건 PostgreSQL의 의도된 격리 모델입니다.
다른 데이터베이스에 접근하려면 두 가지 우회 경로가 있습니다.
| 우회 | 방법 | 비고 |
|---|---|---|
postgres_fdw | 다른 DB(같은 클러스터든 다른 클러스터든)를 외부 테이블로 매핑 | 표준 SQL/MED, Part XVI 참고 |
dblink 확장 | 함수 호출로 다른 DB 쿼리 | 조인 자체는 불가능, 결과 returning |
자동 생성되는 세 데이터베이스
initdb가 클러스터를 초기화하면 데이터베이스 세 개가 미리 들어갑니다.
| 데이터베이스 | 역할 |
|---|---|
postgres | 관리용·기본 접속 데이터베이스. 유틸리티·서드파티 도구가 디폴트로 쓴다 |
template1 | 새 데이터베이스(CREATE DATABASE foo) 생성 시 복제되는 템플릿. 여기 객체를 만들어 두면 이후 만든 모든 DB에 자동으로 들어간다 |
template0 | 원본 백업 템플릿. 절대 수정하지 않는다. pg_dump·복구 시 깨끗한 베이스로 사용 |
데이터 디렉토리 (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 링크 |
| WAL | pg_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/ | 알림·스냅샷·통계·동적 공유 메모리 |
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 | 데이터 페이지 체크섬 활성 (이후 변경 불가, 운영 권장) |
-U <user> | 슈퍼유저 이름 (기본 postgres) |
--wal-segsize=<MB> | WAL 세그먼트 크기 변경 (기본 16MB, 일부 워크로드에서 64MB·128MB 고려) |
initdb는 다음을 수행한다:
- PGDATA 디렉토리 권한 0700(또는 0750)으로 설정
PG_VERSION작성- 시스템 카탈로그 +
template0·template1·postgres생성 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 5433Debian/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활성 권장 (이후 변경 불가)- 한 호스트에 클러스터 여러 개 가능 — 포트·소켓·PGDATA로 격리
다음 절(1.3)에서는 postmaster가 실제로 어떤 프로세스 가족을 띄우는지 — backend·background worker·autovacuum launcher 등 — 봅니다.