콘텐츠로 이동

(KO) PostgreSQL 트랜잭션과 복구 — 섹션 개요

목차

이 서브카테고리는 트랜잭션 코어다. PostgreSQL을 동시에 안전하고 내구적으로 만드는 두 기계, 그리고 그 설계 선택의 대가를 치르는 배경 기계가 함께 담긴다. 그 대가란 no-overwrite, 다중 버전 힙에서 발생하는 비용이다.

한 문장으로 정리하면 이렇다.

  • 동시성 (MVCC). 독자는 스냅샷을 본다. 스냅샷이란 자신에게 가시적인 트랜잭션들의 집합이다. 스냅샷은 procarray — 공유 메모리 안에서 모든 실행 중 백엔드의 XID를 관리하는 목록(storage/ipc/procarray.c) — 에서 GetSnapshotData가 계산한다. 스냅샷에 대한 튜플 가시성은 access/heap/heapam_visibility.c에서 결정되고, 스냅샷의 수명은 스냅샷 매니저(utils/time/snapmgr.c)가 관리한다. procarray는 접합부다. server-architecture 기반이 소유하지만, 모든 스냅샷이 읽는 대상이기 때문에 이 섹션은 postgres-mvcc-snapshots.mdpostgres-procarray.md를 함께 소유한다. procarray는 구조 내부를 다루고, mvcc-snapshots는 가시성을 다룬다.
  • 커밋 상태. 특정 XID가 커밋됐는지, 중단됐는지, 진행 중인지는 커밋 로그(clog) 에 있다. 서브트랜잭션 부모 관계(subtrans), 선택적 커밋 타임스탬프(commit_ts), 공유 락 그룹 멤버십(multixact)도 여기에 포함된다. 이 네 가지는 모두 SLRU — 고정 크기의 추가 전용 로그를 위한 단순한 최근 미사용 페이지 캐시 — 위에서 동작한다. 네 클라이언트가 SLRU를 공유하므로, SLRU는 독립적인 기반 문서로 다룬다.
  • WAL 내구성 척추. Write-Ahead Log(선행 기록 로그)는 PostgreSQL의 단일 redo 스트림이다. access/transam/xact.c가 트랜잭션 상태 기계를 구동하고 커밋 레코드를 기록한다. xlog.c / xloginsert.c가 레코드를 삽입한다. 모든 레코드에는 리소스 매니저(rmgr) 태그가 붙어 있고, rmgr이 redo 콜백을 제공한다. 시작 시 startup 프로세스가 스트림을 재생하고(xlogrecovery.c), checkpointer가 주기적으로 재생 시작점의 하한을 결정한다. 2단계 커밋(2PC) 은 prepared 트랜잭션의 상태를 영속화해, 다른 백엔드나 복구 과정이 나중에 커밋할 수 있도록 한다.
  • 회수. 힙이 덮어쓰지 않으므로 죽은 버전이 쌓인다. Vacuum(commands/vacuum.c, access/heap/vacuumlazy.c)이 이를 회수하고, autovacuum이 그 작업을 스케줄하며, freeze / wraparound 기계(access/heap/heapam.c, access/transam/varsup.c)가 32비트 XID 공간이 넘치지 않게 막는다.

명확한 경계 — 이 섹션이 다루지 않는 것:

  • 공유 메모리 세그먼트, PGPROC/ProcGlobal, LWLock, 헤비웨이트 락 테이블, SSI/서술 락server-architecture에 속한다. 이 섹션은 procarray를 소비하고 락을 획득하지만, 락 매니저나 IPC 기반을 설명하지 않는다. procarray 구조만큼은 MVCC 접합부와 분리할 수 없어 이 섹션으로 끌어들인 유일한 예외다.
  • 페이지, 버퍼, smgr, 힙 튜플 형식, HOT 프루닝, 테이블 AM, 가시성 맵, TOASTstorage-engine에 속한다. 이 섹션은 어떤 버전이 가시적인지, 언제 회수할 수 있는지를 결정한다. 버전이 페이지에 어떻게 배치되고 flush되는지는 storage 섹션이 소유한다. WAL-before-flush 규칙과 가시성 맵이 공유 접합부다.
  • 스트리밍/논리 복제, 복제 슬롯, 아카이빙, 베이스 백업, PITRreplication-ha에 속한다. 이것들은 이 섹션이 생성하는 WAL 스트림의 소비자다. 생성 측과 redo/복구 측은 여기에, 배포 측은 저기에 있다.

이 섹션이 소유하는 것은 스냅샷 계산, 커밋 상태 기록, WAL 생성·redo, 죽은 버전 회수다. 기반은 server-architecture와 storage-engine으로 내려 보내고, WAL 스트림은 replication-ha로 옆으로 건넨다.

이 서브카테고리는 하나의 기반 위에서 동작하는 두 기계로 읽는 것이 가장 자연스럽다. 두 기계는 커밋에서 만난다. 왼쪽 열은 MVCC·가시성 기계이고, 오른쪽 열은 WAL·내구성 기계다. 회수 기계는 아래에서 MVCC가 남긴 것을 되돌린다.

flowchart TB
  subgraph SUBSTRATE["공유 메모리 기반 (server-architecture 소유)"]
    PARR["postgres-procarray<br/>실행 중 XID 목록, GetSnapshotData"]
  end

  subgraph MVCC["동시성 기계 — 무엇이 보이는가"]
    SNAP["postgres-mvcc-snapshots<br/>스냅샷 + 튜플 가시성"]
    CLOG["postgres-clog-commit-ts<br/>커밋/중단 상태, 커밋 타임스탬프"]
    MXACT["postgres-multixact<br/>공유 행 락, 락 그룹"]
    SLRU["postgres-slru<br/>clog/subtrans/commit_ts/multixact 공용 페이지 캐시 기반"]
  end

  subgraph WAL["내구성 기계 — redo 척추"]
    XACT["postgres-xact<br/>트랜잭션 상태 기계, 커밋 레코드"]
    XLOG["postgres-xlog-wal<br/>WAL 삽입, 세그먼트, 제어 상태"]
    RMGR["postgres-wal-records-rmgr<br/>rmgr별 레코드 형식 + redo 콜백"]
    TWOPC["postgres-two-phase-commit<br/>PREPARE / COMMIT PREPARED 상태"]
    REDO["postgres-recovery-redo<br/>startup 프로세스: 크래시 + 아카이브 재생"]
    CKPT["postgres-checkpoint<br/>checkpointer: redo 시작점 결정"]
  end

  subgraph RECLAIM["회수 — no-overwrite 비용 청산"]
    VAC["postgres-vacuum<br/>lazy vacuum: 프루닝, 동결, 회수"]
    AV["postgres-autovacuum<br/>런처 + 워커: 스케줄링"]
    FREEZE["postgres-xid-wraparound-freeze<br/>동결 + 32비트 XID 순환 방어"]
  end

  PARR --> SNAP
  SNAP --> CLOG
  CLOG --> SLRU
  MXACT --> SLRU
  SNAP -. "커밋 상태 읽기" .-> CLOG

  XACT --> XLOG
  XACT --> CLOG
  XLOG --> RMGR
  XACT --> TWOPC
  XLOG --> REDO
  RMGR -. "redo 콜백" .-> REDO
  CKPT --> XLOG
  CKPT -. "재생 범위 결정" .-> REDO

  SNAP -. "가장 오래된 가시 XID 계산" .-> VAC
  AV --> VAC
  VAC --> FREEZE
  FREEZE -. "동결 지평 전진" .-> CLOG

두 기계는 커밋에서 만난다. xact가 WAL 커밋 레코드를 쓰는 동시에 clog에 도장을 찍는다. 회수 기계가 그 순환을 닫는다. vacuum은 procarray·스냅샷 측에서 가장 오래된 스냅샷의 가시 XID 지평을 가져다 어느 죽은 버전을 안전하게 제거할 수 있는지 판단하고, freeze는 동결 XID 지평을 전진시켜 오래된 clog 페이지를 잘라낼 수 있게 한다. SLRU는 왼쪽 전체를 조용히 떠받치는 기반이다.

상호 참조 우선 순서다. 의존 관계가 있는 문서들보다 스냅샷 접합부와 WAL 척추를 먼저 읽는다.

  1. 스냅샷 접합부postgres-procarray.md, 이어서 postgres-mvcc-snapshots.md. procarray는 구조이고, MVCC 스냅샷은 그로부터 계산하는 것이다. 두 문서를 한 쌍으로 읽는다.
  2. 커밋 상태와 그 기반postgres-slru.md를 먼저(페이지 캐시), 이어서 postgres-clog-commit-ts.mdpostgres-multixact.md(그 클라이언트들). 가시성 판정이 clog를 읽으므로 MVCC 뒤에 온다.
  3. 트랜잭션 + WAL 척추postgres-xact.md(상태 기계와 커밋 프로토콜), 이어서 postgres-xlog-wal.md(로그 자체), 이어서 postgres-wal-records-rmgr.md(레코드 형식과 redo 콜백).
  4. 복구와 그 범위postgres-recovery-redo.md(스트림을 재생하는 startup 프로세스), 이어서 postgres-checkpoint.md(재생이 어디서 시작할지를 결정하는 것).
  5. 분산 커밋postgres-two-phase-commit.md(xact + WAL + 복구를 기반으로 한다).
  6. no-overwrite 비용 청산postgres-vacuum.md, 이어서 postgres-autovacuum.md(스케줄링), 이어서 postgres-xid-wraparound-freeze.md(vacuum이 궁극적으로 존재하는 이유인 순환 방어).

세 편만 읽는다면: procarray → mvcc-snapshots → xact. 이 셋이 스냅샷 접합부와 커밋을 이름 붙이며, 나머지 모든 것이 거기서 걸린다. 트리 내의 access/transam/README(“The Transaction System”)는 3단계의 표준 동반 문서로, postgres-xact.md와 함께 읽을 만하다.

전방 참조다. 아래 모듈 문서들은 계획된 상태이며, 요약은 예측적이다. 각 문서가 소유할 내용을 기술한다.

모듈 문서다루는 내용 (한 줄)
postgres-mvcc-snapshots.md스냅샷이 무엇인지, GetSnapshotData가 procarray에서 어떻게 스냅샷을 만드는지, HeapTupleSatisfiesMVCC가 스냅샷 기준으로 튜플 가시성을 어떻게 결정하는지.
postgres-procarray.md공유 메모리 안의 실행 중 XID 목록: ProcArray 구조체, XID 할당·반납, 스냅샷 계산, vacuum이 의존하는 xmin 지평.
postgres-xact.md3계층 트랜잭션 상태 기계(StartTransactionCommand/CommitTransactionCommand), 서브트랜잭션, 저장점, WAL 커밋 레코드 + clog 도장.
postgres-xlog-wal.mdWAL 레코드 삽입(XLogInsert), LSN, pg_wal/의 WAL 세그먼트, 제어 파일, WAL-before-flush 내구성 규칙.
postgres-wal-records-rmgr.md리소스 매니저 테이블: 각 레코드가 rmgr 태그를 받고 redo/desc/decode 콜백으로 디스패치되는 방식; 제네릭 WAL.
postgres-slru.mdclog, subtrans, commit_ts, multixact가 공유하는 단순 LRU 페이지 캐시 기반(SimpleLruInit) — 버퍼링, I/O, 잘라내기.
postgres-clog-commit-ts.md커밋 로그(XID별 커밋/중단/진행 중), 서브트랜잭션 부모 관계, 선택적 트랜잭션별 커밋 타임스탬프.
postgres-multixact.mdMultiXact ID: 여러 트랜잭션이 잠근/공유한 행을 PostgreSQL이 어떻게 표현하는지, 그 뒤의 offset/member SLRU.
postgres-two-phase-commit.mdPREPARE TRANSACTION / COMMIT PREPARED: 디스크 상의 TwoPhaseFileHeader 상태, 2PC rmgr 레코드, prepared 트랜잭션 복구.
postgres-recovery-redo.mdstartup 프로세스: 크래시 vs 아카이브 복구, WAL 스트림 위의 redo 루프, 타임라인, 복구 대상(PITR), WAL 프리페치.
postgres-checkpoint.md체크포인트란 무엇인지, checkpointer 프로세스(CheckpointerMain), CreateCheckPoint가 redo 시작점을 어떻게 결정하는지, 체크포인트 페이싱.
postgres-vacuum.mdvacuumlazy.c의 lazy vacuum 3단계(프루닝+동결, 인덱스 vacuum, 회수), 죽은 TID 추적, 병렬 vacuum 디스패치.
postgres-autovacuum.mdautovacuum 런처 + 워커: 임계값, 테이블별 스케줄링, vacuum을 강제하는 순환 긴급 경로.
postgres-xid-wraparound-freeze.md32비트 XID 공간, 튜플 동결(heap_prepare_freeze_tuple), varsup.c XID 할당 + 한도, 순환 방어.
섹션 개요인접한 이유
postgres-overview-server-architecture.md이 섹션이 올라서는 공유 메모리 기반을 소유한다: PGPROC/ProcGlobal, LWLock, 헤비웨이트 락 테이블, SSI/서술 락, checkpointer·bgwriter·startup 보조 프로세스. procarray 구조만 이 섹션이 끌어들인 예외이며, 그 아래의 모든 것은 저쪽에 머문다.
postgres-overview-storage-engine.md페이지, 버퍼 풀, smgr, 힙 튜플 형식, HOT 프루닝, 테이블 AM, 가시성 맵, TOAST를 소유한다. 이 섹션은 어떤 튜플 버전이 가시적인지, 언제 회수할 수 있는지를 결정하고, storage 섹션은 버전이 페이지에 어떻게 배치되고 flush되는지를 소유한다. WAL-before-flush 규칙과 가시성 맵이 공유 접합부다.
postgres-overview-replication-ha.md이 섹션이 생성하고 redo하는 WAL 스트림의 하류 소비자다: 물리 스트리밍, 논리 디코딩, 아카이빙, 베이스 백업, PITR이 모두 같은 로그를 읽는다. 복구·redo 측은 여기에, 배포 측은 저기에 있다.
postgres-overview-query-processing.md경계가 가볍다. 실행기가 스냅샷을 열고, 여기서 경계 지은 트랜잭션 블록이 질의 실행을 감싼다. 스냅샷 수명(snapmgr)이 접점이다. 실행기 자체는 query-processing에 머문다.