※ PostgreSQL: Streaming-replication Lag.
안녕하세요. 듀스트림입니다.
오늘 포스팅은 PostgreSQL에서 스트리밍 복제 지연 발생 시 분석 방법에 대한 내용입니다.
결론부터 말씀드리면 주로 발생하는 지연 원인은 경험상 아래 정도가 있는 것 같습니다.
- 대부분 비동기 복제 정책 문제 (95% 이상)
- 배치, Autovacuum, 인덱스 재작성 등 피크 타임에 WAL 폭증
- 너무 잦은 체크포인트
- Primary와 Standby의 스토리지 차이(NVME, SSD, HDD)
- 네트워크 지터
1. 어디에서 느린건지 구분
▸ 복제 동작은 크게 아래 3단계로 볼 수 있습니다:
WAL 생성 → 전송/수신 → 재생(리플레이)
→ 이 중 어디가 느린지에 따라 원인이 갈립니다.
1.1 Primary에서 확인
-- 세션별 전송/기록/재생 지연 확인
SELECT pid, application_name, state,
write_lag, -- 보낸 WAL을 스탠바이가 'write'까지 걸린 시간
flush_lag, -- 'flush'까지 걸린 시간
replay_lag, -- 'replay'(적용)까지 걸린 시간
sent_lsn, write_lsn, flush_lsn, replay_lsn,
sync_state -- async / sync / quorum ...
FROM pg_stat_replication;
→ write_lag/flush_lag가 크면 전송·수신·디스크쓰기 문제, replay_lag만 크면 스탠바이 리플레이 병목일 가능성이 큽니다.
27.2. The Cumulative Statistics System
27.2. The Cumulative Statistics System # 27.2.1. Statistics Collection Configuration 27.2.2. Viewing Statistics 27.2.3. pg_stat_activity 27.2.4. pg_stat_replication 27.2.5. pg_stat_replication_slots 27.2.6. pg_stat_wal_receiver …
www.postgresql.org
1.2 Standby에서 확인
-- 스탠바이가 얼마만큼 따라잡았는지(적용되었는지)
-- 시간 지연
SELECT now() - pg_last_xact_replay_timestamp() AS apply_delay;
→ 참고로 이 함수는 프라이머리가 한가할 때는 "지연처럼" 보일 수 있어 해석에 주의해야 합니다. (거래가 드물면 최근 커밋 타임스탬프가 오래되어 지연으로 오인될 수 있음)
-- WAL 수신 상태(스탠바이)
SELECT * FROM pg_stat_wal_receiver;
→ 여기서 last_msg_send_time / last_msg_receipt_time, latest_end_lsn 등을 보면 네트워크/수신 측 상태를 파악할 수 있습니다.
2. 패턴별 원인과 해결 가이드
2.1 write_lag/flush_lag ↑ (전송·수신·디스크 쓰기 측 병목)
▸ 가능한 원인
- 네트워크 지터/패킷 손실/MTU 불일치
- 스탠바이 디스크 쓰기 지연(저속 스토리지, flush 대기, 체크포인트 타이밍 겹침)
- WAL 폭증(대량 DML/Autovacuum 대규모 청소/대량 인덱스 재작성 등)
▸ 점검/개선
- 네트워크: 인터페이스 에러/재전송, MTU, TCP offload, RTT 모니터링
- 스토리지: 스탠바이 I/O 대기 시간, 체크포인트 설정(아래), WAL 파일 flush 대기
- 체크포인트/ WAL 양 줄이기:
- checkpoint_timeout, max_wal_size, checkpoint_completion_target 재조정
- 불필요한 대량 변경 피크 분산, Autovacuum 튜닝(테이블별 aggressive vacuum 방지)
- 프라이머리 WAL 보존: (PG13+) wal_keep_size 또는 (구버전) wal_keep_segments 적정값 설정으로 재전송·재요청 부담 완화 (명칭/의미 변경 주의)
2.2 replay_lag만 ↑ (스탠바이 적용이 느린 경우)
▸ 가능한 원인
- 스탠바이 단일 스레드 리플레이가 I/O 바운드 (대량 업데이트/인덱스 유지비용/FPW 등)
- 스탠바이에서 동시에 읽기 트래픽이 많아 리플레이와 I/O 경합
- 체크포인트 직후 더 많은 더티 페이지 쓰기로 리플레이가 밀림
▸ 점검/개선
- 스탠바이 I/O/CPU 모니터링으로 리플레이가 I/O 바운드인지 확인
- 스토리지 성능 개선 또는 스탠바이에 리더 전용 트래픽을 분산
- 체크포인트/Autovacuum/인덱스 유지 비용이 리플레이와 충돌하지 않도록 스케줄·파라미터 조정
2.3 프라이머리가 항상 바쁜데 시간 기반 지연 지표가 크게 보이는 경우
- pg_last_xact_replay_timestamp() 기반 시간 차이는 프라이머리가 유휴일 때도 지연처럼 보일 수 있으니, LSN 차이 및 pg_stat_replication의 _lag 칼럼을 함께 확인보시길 바랍니다.
2.4 비동기 복제 구성이라 의도된 지연이 발생
- synchronous_commit = off/remote_write/on/remote_apply 및 synchronous_standby_names 값에 따라 커밋 대기가 달라집니다.
- 완전 동기(특히 remote_apply) 로 갈수록 프라이머리 TPS는 떨어지지만, 스탠바이 가시성 지연은 사실상 0에 수렴합니다(대기 비용을 프라이머리로 전가).
3. 원인 분리 체크리스트
3.1 세션별 lag 스냅샷
SELECT now() AS ts, application_name, state,
write_lag, flush_lag, replay_lag,
sent_lsn, write_lsn, flush_lsn, replay_lsn
FROM pg_stat_replication;
→ 1분 간격으로 몇 번 수집해 패턴을 봅니다. write/flush가 튀면 전송·수신 측, replay만 튀면 적용 측 이슈.
3.2 스탠바이 수신 상태
SELECT now() AS ts, status, conninfo,
last_msg_send_time, last_msg_receipt_time, latest_end_lsn
FROM pg_stat_wal_receiver;
→ last_msg_* 차이가 크면 네트워크/수신 지연 신호입니다.
3.3 시간 기반 지연 (적용 기준)
SELECT now() - pg_last_xact_replay_timestamp() AS apply_delay;
→ 이 값은 해석에 주의 해야합니다(프라이머리 유휴 시 오판 가능). 반드시 LSN 지표와 함께 체크하시길 바랍니다.
3.4 체크포인트 영향
체크포인트 직후 replay_lag가 급증하면 checkpoint_timeout / max_wal_size / checkpoint_completion_target 재조정을 고려하시길 바랍니다.
3.5 WAL 보존/회수
Primary의 wal_keep_size(또는 구버전 wal_keep_segments)가 너무 작아 잦은 재요청·재전송이 생기지 않는지 점검이 필요합니다.
3.6 구성 정책 확인
동기/비동기, synchronous_standby_names, synchronous_commit 정책이 의도한 RPO/RTO와 맞는지 재점검이 필요합니다.
(엄격한 실시간 가시성이 필요하면 remote_apply 고려)
※ 아래와 같이 설정하면 COMMIT 시 Standby 적용까지 기다립니다. (대신 Primary의 대기시간이 증가합니다.)
synchronous_standby_names = 'FIRST 1 (node2, node3, ...)'
synchronous_commit = remote_apply
오늘은 여기까지~
'PostgreSQL' 카테고리의 다른 글
| PostgreSQL: SELECT 효율 분석 (0) | 2025.11.21 |
|---|---|
| PostgreSQL: DISTINCT ON (0) | 2025.11.19 |
| PostgreSQL: never executed (0) | 2025.11.10 |
| PostgreSQL: ctid (0) | 2025.11.07 |
| PostgreSQL: Heap Table Structure (0) | 2025.11.05 |