(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.md와postgres-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, 가시성 맵, TOAST는 storage-engine에 속한다. 이 섹션은 어떤 버전이 가시적인지, 언제 회수할 수 있는지를 결정한다. 버전이 페이지에 어떻게 배치되고 flush되는지는 storage 섹션이 소유한다. WAL-before-flush 규칙과 가시성 맵이 공유 접합부다.
- 스트리밍/논리 복제, 복제 슬롯, 아카이빙, 베이스 백업, PITR은 replication-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 척추를 먼저 읽는다.
- 스냅샷 접합부 —
postgres-procarray.md, 이어서postgres-mvcc-snapshots.md. procarray는 구조이고, MVCC 스냅샷은 그로부터 계산하는 것이다. 두 문서를 한 쌍으로 읽는다. - 커밋 상태와 그 기반 —
postgres-slru.md를 먼저(페이지 캐시), 이어서postgres-clog-commit-ts.md와postgres-multixact.md(그 클라이언트들). 가시성 판정이 clog를 읽으므로 MVCC 뒤에 온다. - 트랜잭션 + WAL 척추 —
postgres-xact.md(상태 기계와 커밋 프로토콜), 이어서postgres-xlog-wal.md(로그 자체), 이어서postgres-wal-records-rmgr.md(레코드 형식과 redo 콜백). - 복구와 그 범위 —
postgres-recovery-redo.md(스트림을 재생하는 startup 프로세스), 이어서postgres-checkpoint.md(재생이 어디서 시작할지를 결정하는 것). - 분산 커밋 —
postgres-two-phase-commit.md(xact + WAL + 복구를 기반으로 한다). - 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.md | 3계층 트랜잭션 상태 기계(StartTransactionCommand/CommitTransactionCommand), 서브트랜잭션, 저장점, WAL 커밋 레코드 + clog 도장. |
postgres-xlog-wal.md | WAL 레코드 삽입(XLogInsert), LSN, pg_wal/의 WAL 세그먼트, 제어 파일, WAL-before-flush 내구성 규칙. |
postgres-wal-records-rmgr.md | 리소스 매니저 테이블: 각 레코드가 rmgr 태그를 받고 redo/desc/decode 콜백으로 디스패치되는 방식; 제네릭 WAL. |
postgres-slru.md | clog, subtrans, commit_ts, multixact가 공유하는 단순 LRU 페이지 캐시 기반(SimpleLruInit) — 버퍼링, I/O, 잘라내기. |
postgres-clog-commit-ts.md | 커밋 로그(XID별 커밋/중단/진행 중), 서브트랜잭션 부모 관계, 선택적 트랜잭션별 커밋 타임스탬프. |
postgres-multixact.md | MultiXact ID: 여러 트랜잭션이 잠근/공유한 행을 PostgreSQL이 어떻게 표현하는지, 그 뒤의 offset/member SLRU. |
postgres-two-phase-commit.md | PREPARE TRANSACTION / COMMIT PREPARED: 디스크 상의 TwoPhaseFileHeader 상태, 2PC rmgr 레코드, prepared 트랜잭션 복구. |
postgres-recovery-redo.md | startup 프로세스: 크래시 vs 아카이브 복구, WAL 스트림 위의 redo 루프, 타임라인, 복구 대상(PITR), WAL 프리페치. |
postgres-checkpoint.md | 체크포인트란 무엇인지, checkpointer 프로세스(CheckpointerMain), CreateCheckPoint가 redo 시작점을 어떻게 결정하는지, 체크포인트 페이싱. |
postgres-vacuum.md | vacuumlazy.c의 lazy vacuum 3단계(프루닝+동결, 인덱스 vacuum, 회수), 죽은 TID 추적, 병렬 vacuum 디스패치. |
postgres-autovacuum.md | autovacuum 런처 + 워커: 임계값, 테이블별 스케줄링, vacuum을 강제하는 순환 긴급 경로. |
postgres-xid-wraparound-freeze.md | 32비트 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에 머문다. |