postgres backup(pgbackrest)

코드깎는 노인·2024년 10월 22일
0

1. 용어

전체백업

현재 데이터베이스의 전체 백업.첫번쨰 백업은 반드시 전체백업이어야 한다.전체 백업은 자신 이외의 파일을 참조하지 않음

차등백업

마지막 전체백업 이후 변경사항에 대해 백업.차등백업으로 복구시 의존하는 전체백업도 유효해야됨

증분백업

마지막 백업이후 변경사항에 대해 백업.증분백업이 의존하고 있는 증분백업,차등,전체백업이 유효해야 정상작동

WAL(Write-Ahead Logging)

  • 정의

    	- 데이터베이스의 변경사항을 실제 데이터 파일에 쓰기 전에 로그에 먼저 기록하는 기법
  • 작동 방식

    	- 데이터 변경 요청 발생
    
    	- 변경 내용을 WAL 파일에 기록
    
    	- WAL 파일이 디스크에 안전하게 저장되었음을 확인
    
    	- 실제 데이터 파일 변경
  • WAL의 주요 목적:

    	- 데이터 일관성 보장:
    
    		- 시스템 충돌 시 WAL을 사용하여 불완전한 트랜잭션을 롤백하거나 완료할 수 있습니다
    
    	- 성능 향상
    
    		- 무작위 쓰기 대신 순차적 쓰기를 사용하여 I/O 성능을 개선
    
    	- 시점 복구 지원
    
    		- 특정 시점으로의 데이터베이스 복구를 가능
  • WAL의 구조:

    	- 일련의 16MB (기본 크기) 세그먼트 파일로 구성됩니다.
    
    	- 각 세그먼트는 연속된 트랜잭션 로그를 포함합니다.
  • WAL의 중요성:

    	- 장애 복구
    
    		- 시스템 충돌 후 데이터베이스를 일관된 상태로 복구할 수 있습니다.
    
    	- 복제
    
    		- 스트리밍 복제를 통해 실시간으로 대기 서버를 동기화
    
    	- 백업
    
    		- 온라인 백업과 시점 복구를 가능하게 합니다.
  • WAL 관리:

    	- WAL 아카이빙: 완료된 WAL 세그먼트를 안전한 위치에 저장합니다.
    
    	- WAL 보관: 필요한 기간 동안 WAL 파일을 유지합니다.
    
    	- 체크포인트: 주기적으로 변경된 데이터를 디스크에 기록하고 WAL을 정리합니다

stanza

  • Postgresql데이터베이스에 대한 설정,백업온션,아카이브 옵션

2. 설정

postgresql.conf

archive_command = 'pgbackrest --stanza=my_stanza archive-push /var/lib/postgresql/data/%p'
archive_mode = on
max_wal_senders = 3
wal_level = replica
archive_timeout = 60
  • 공식문서에는 archive_command = 'pgbackrest --stanza=demo archive-push %p' 으로 나와있지만 실제 명령어 실행시 경로가 맞지 않아 /var/lib/postgresql/data/%p으로 변경함

  • postgresql/copy.sh 스크립트로 도커 공유 볼륨 수정

  • archive_timeout = 60: wal사이즈(15mb)를 충족하지 않아도 특정 시간이 되면 wal파일 스위치하여 60초마다 wal파일 푸시

pgbackrest.conf

[global]
...
repo1-retention-full=4
repo1-retention-full-type=count
repo1-retention-diff=7
repo1-retention-archive=1
repo1-retention-archive-type=diff

[my_stanza]
pg1-path=/var/lib/postgresql/data
pg1-user=sohatech
pg1-database=sohatechfarmdb
  • 리텐션은 갯수(count)와 기간(time,일)로 설정가능하다

  • my_stanza: stanza이름

  • pg1-path:postgres디렉토리

도커 볼륨 생성 및 설정파일 복사

pgbackrest/copy.sh 실행

stanza생성

pgbackrest --stanza=my_stanza --log-level-console=info stanza-create

stanza확인

pgbackrest --stanza=my_stanza --log-level-console=info check
pgbackrest --stanza=my_stanza --log-level-console=info stanza-upgrade
  • 정상적으로 확인되지 않을경우 /var/lib/pgbackrest의 my_stanza삭제후 다시 생성 필요에 따라 upgrade를 통하여 에러 해결 가능

repository생성 및 권한설정정

chown -R postgres:postgres /var/lib/pgbackrest && chmod -R 750 /var/lib/pgbackrest && chown -R postgres:postgres /var/log/pgbackrest

실질적으로 백업이 저장되는 공간

3.명령어

컨네이너 접속

docker exec -it pg bash

백업

pgbackrest --stanza=my_stanza --type=full backup --log-level-console=info
pgbackrest --stanza=my_stanza --type=diff backup --log-level-console=info
pgbackrest --stanza=my_stanza --type=incr backup --log-level-console=info

백업 리스트 확인

pgbackrest --stanza=my_stanza  info

DB 정지/시작

su postgres 
pg_ctl stop
pg_ctl start
  • pg_ctl은 root모드로 실행되지 않으므로 postgres유저로 접속한다

  • 백업전 stop,백업 후 start

백업 아이디로 복구

pgbackrest restore --stanza=my_stanza --set=20241018-090125F --delta --target-action=promote --type=immediate
  • --type=immediate: 복구시점이후 wal이 적용되지 않음.적용하지 않으면 백업 시점 이후의 모든 변경사항이 자동으로 적용되어, 결과적으로 최신 상태의 데이터베이스가 복원

  • --target-action=promote:복구완료후 즉시 프로덕션 환경으로 승격하여 서비스 활성화

  • --delta:현재데이터베이스와 비교하여 차이점만 복구,이 옵션없으면 현재 데이터베이스 완전 삭제후 실행가능

시점으로 복구(PITR)

psql -U sohatech -d sohatechfarmdb -Atc"select current_timestamp"

pgbackrest --stanza=my_stanza  restore --type=time "--target=2024-10-21 06:23:46+00" --delta  --target-action=promote
  • 쿼리를 통해 db시간을 확인하고 db시간에 맞춰 시간을 조절한다

복구 후 프로덕션 모드 확인

psql -U sohatech -d sohatechfarmdb -c "SELECT pg_is_in_recovery();"
psql -U sohatech -d sohatechfarmdb -c "SELECT pg_wal_replay_resume();"
  • recovery모드가 T일경우 resume명령어 실행

마지막 아카이브 시점 확인

pg_controldata -D $PGDATA | grep -E "Latest checkpoint|Time of latest" 
pg_waldump -p /path/to/pgbackrest/archive /path/to/last/wal/file

4. 에러 핸들링

시간 역행 문제

  • 시나리오

    	- 시점 A의 백업에서 복구
    
    	- 시점시점 B (A 이후)까지 WAL 적용
    
    	- 시점다시 A와 B 사이의 시점 C로 복구 시도
  • 문제

    	- B 이후의 WAL이 이미 적용되어 C 시점으로의 정확한 복구 어려움
  • 해결

    	- A 시점부터 새로 복구를 시작하고 C 시점까지만 WAL 적용

특점시점으로 복구 후 wal파일 내부작동

  • WAL 아카이브 보존:

    	- 복구 시점 A까지의 WAL 파일들은 계속 유지
    
    	- WAL 파일들은 백업의 일관성을 유지하기 위해 필요하기 때문
  • WAL 파일 처리:

    	- 복구 시점 A 이후의 WAL 파일들은 무시
    
    	- PostgreSQL은 복구 시점 A까지만 WAL을 재생하고 그 이후의 WAL은 적용하지 않음
    
    	- 하지만 실제 WAL 파일이 물리적으로 삭제되지는 않음음
  • 새로운 타임라인:

    	- 복구 완료 후 새로운 타임라인이 생성
    
    	- 이는 복구 시점 A 이후의 데이터베이스 변경사항이 원본과 다른 분기로 진행됨
  • WAL 아카이브 관리:

    	- 기존의 WAL 파일들은 repo-retention-archive 설정에 따라 관리
    
    	- 백업 보존 정책에 따라 불필요한 WAL 파일은 expire 명령어로 제거

repo1-retention-archive=1의미

시나리오:
1. 전체 백업 수행 (Full Backup) - WAL 위치: 000000010
2. WAL 아카이브 생성 - 000000011, 000000012, 000000013
3. 차등 백업 A 수행 - WAL 위치: 000000014
4. WAL 아카이브 생성 - 000000015, 000000016, 000000017
5. 차등 백업 B 수행 - WAL 위치: 000000018

repo1-retention-archive=1인 경우:

  • 차등 백업 A의 시점에서는 000000014부터의 WAL만 유지

  • 차등 백업 B의 시점에서는 000000018부터의 WAL만 유지

  • 이전 WAL들(000000015-000000017)은 제거됨

이는 다음을 의미

  • 각 백업 시점으로의 복구는 항상 가능

  • PITR(Point-in-Time Recovery)은 가장 최근 백업 이후의 시점으로만 가능

  • 오래된 WAL 아카이브는 자동으로 제거되어 디스크 공간 절약

만약 repo1-retention-archive=2로 설정하면:

  • 두 개의 연속된 백업 사이의 모든 WAL을 유지

  • 더 많은 과거 시점으로의 PITR이 가능

  • 하지만 더 많은 디스크 공간 사용

문서의 예시를 보면:


P00 DETAIL: repo1: 15-1 archive retention on backup 20241021-052042F, start = 00000002000000000000000C, stop = 00000002000000000000000D
P00 DETAIL: repo1: 15-1 archive retention on backup 20241021-052042F_20241021-052048D, start = 000000020000000000000012, stop = 000000020000000000000013
P00   INFO: repo1: 15-1 remove archive, start = 00000002000000000000000E, stop = 000000020000000000000011

여기서:

  • 각 백업의 시작/종료 WAL은 유지됨

  • 백업 사이의 중간 WAL(000000E-000000011)은 제거됨

  • 그러나 백업의 일관성에 필요한 WAL은 항상 보존됨

profile
내가 볼려고 만든 블로그

0개의 댓글