{#backup-backup-and-recovery} # 백업과 복구 그래프는 PostgreSQL 스키마와 테이블로 저장되므로, 모든 PostgreSQL 백업 방법이 그래프를 담으며, 관계형 데이터와 같은 시점으로 담습니다. 따로 받아야 할 그래프 백업도, 따로 맞춰야 할 복원도 없습니다. 그러므로 [PostgreSQL의 백업 장](https://www.postgresql.org/docs/18/backup.html)이 레퍼런스이고, 이 페이지는 선택지와 그래프에만 해당하는 세부를 다룹니다. {#backup-which-method} ## 어느 방법을 쓸 것인가 | 방법 | 얻는 것 | 언제 쓰는가 | | --- | --- | --- | | `pg_dump` / `pg_dumpall` | 논리적 사본입니다. SQL 문장 또는 아카이브이며, 메이저 버전과 플랫폼을 넘어 이식됩니다. | 데이터베이스를 옮길 때, 그래프 하나를 복사할 때, 버전에 매이지 않는 사본을 둘 때. | | `pg_basebackup` | 클러스터 전체의 물리적 사본입니다. | 시점 복구 구성의 기반, 그리고 복제본을 처음 채울 때. | | 연속 아카이빙 | 베이스 백업에 그 뒤의 모든 WAL 세그먼트를 더한 것이며, 어느 순간으로든 복구할 수 있습니다. | 운영 환경. 한 시간 치 쓰기를 잃는 것이 용납되지 않는 곳. | | 파일시스템 스냅샷 | 스토리지 계층이 뜨는 물리적 사본입니다. | 클러스터가 쓰는 모든 파일시스템에 걸쳐 스냅샷이 원자적일 때만. | 서버가 도는 중에 `cp`로 데이터 디렉터리를 복사하는 것은 백업이 아닙니다. 테이블 파일을 하나씩 복사하는 것은 결코 백업이 아닙니다. 커밋 로그는 클러스터 전체의 것이므로, 홀로 떠 온 파일은 자기 행 중 무엇이 커밋됐는지 말할 방법이 없습니다. {#backup-logical-backup} ## 논리 백업 ```shell pg_dump -d mydb -Fc -f mydb.dump # one database, archive format pg_dumpall -f cluster.sql # every database plus roles pg_dump -d mydb --schema=moviekb -f g.sql # one graph ``` 복원: ```shell pg_restore --exit-on-error -d mydb mydb.dump psql -d postgres -f cluster.sql ``` ```{warning} 두 도구 모두 기본값이 오류를 만나도 계속 진행하는 것이고, `psql` 은 그러고도 종료 코드 0 을 냅니다. 그래서 객체가 빠진 채로 복원이 «성공» 이라고 보고될 수 있습니다 — 서버가 거부한 제약이 있으면 그 테이블은 제약 없이 만들어지고, 그다음부터 아무것도 참조하지 않는 행이 들어갑니다. `--exit-on-error` 를 주면 `pg_restore` 가 첫 오류에서 멈춥니다. `psql` 에는 `ON_ERROR_STOP` 이 있지만 `pg_dumpall` 산출물에는 쓸 수 없습니다. 그 파일은 이미 존재하는 부트스트랩 슈퍼유저를 다시 만들기 때문에, 14행에서 멈추고 아무것도 적재하지 않습니다. 그 경우에는 출력을 직접 읽거나, 데이터베이스마다 `pg_dump -Fc` 로 따로 덤프해서 `pg_restore --exit-on-error` 로 복원하십시오. ``` 그래프가 곧 스키마이므로, 그래프 하나를 덤프하는 방법은 그 스키마를 지정하는 것입니다. 덤프에는 데이터와 함께 `CREATE GRAPH`·`CREATE VLABEL`·`CREATE ELABEL` 문장이 담기므로, 복원하면 그래프 구조가 다시 만들어집니다. 그래프에만 해당하는 것 네 가지이며, 자세한 내용은 모두 [서버 측 도구](#tools-dumping-a-graph)에 있습니다: * 두 도구 모두 AgensGraph 버전을 검사하지 않고 PostgreSQL 버전만 검사합니다. * 평범한 컬럼을 지닌 레이블의 덤프는 복원할 때 `enable_graph_ddl`이 필요하며, 덤프가 자기 문장을 그것으로 감쌉니다. * 어떤 그래프든 승격된 컬럼을 쓰고 있으면 2.18 덤프는 2.17에 복원되지 않습니다. * Cypher 쿼리로 만든 뷰는 그 Cypher가 컴파일된 SQL로 덤프됩니다. 어떤 복원이든 끝난 뒤에는 그래프 메타데이터와 통계를 다시 만드십시오: ```sql SET graph_path = ; SELECT regather_graphmeta(); ``` ```shell vacuumdb -d mydb --analyze-in-stages ``` {#backup-physical-backup-and-point-in-time-recovery} ## 물리 백업과 시점 복구 동작 방식은 PostgreSQL의 것 그대로입니다. 요약하면: 서버를 아카이빙하도록 설정하고 재기동합니다: ``` wal_level = replica archive_mode = on archive_command = 'test ! -f /mnt/archive/%f && cp %p /mnt/archive/%f' ``` `wal_level = minimal`은 아카이브에서 복구할 만큼을 기록하지 않으므로, 이 방법을 쓸 수 없게 만듭니다. 베이스 백업을 받습니다: ```shell pg_basebackup -D /mnt/backup/base -Ft -z -P -X stream ``` 복구하려면 베이스 백업을 빈 데이터 디렉터리에 풀고, 아카이브된 WAL을 어디서 가져올지 서버에 알려 줍니다: ``` restore_command = 'cp /mnt/archive/%f %p' recovery_target_time = '2026-09-02 14:30:00' ``` 이 값들은 `postgresql.conf`에 넣고, 데이터 디렉터리에 둔 `recovery.signal`이라는 빈 파일이 서버를 복구 모드로 들어가게 합니다. 복구가 끝나면 서버는 그 신호 파일을 지우고 접속을 받기 시작합니다. ```{note} 예전 AgensGraph나 PostgreSQL 문서를 보고 작업한다면 자리를 옮긴 것이 셋 있습니다. 복구 설정은 `recovery.conf`가 아니라 `recovery.signal` 파일과 함께 `postgresql.conf`에 있습니다. 그 파일은 PostgreSQL 12에서 없어졌고, 서버는 그것을 발견하면 기동을 거부합니다. WAL 디렉터리는 `pg_xlog`가 아니라 `pg_wal`이고, 커밋 로그는 `pg_clog`가 아니라 `pg_xact`입니다. 둘 다 PostgreSQL 10에서 이름이 바뀌었습니다. ``` 베이스 백업에 기대기 전에 그것을 검증하십시오: ```shell pg_verifybackup /mnt/backup/base ``` {#backup-higher-level-tools} ## 더 높은 수준의 도구 `pgBackRest`와 `Barman`은 보관 기간·병렬 압축·증분 백업·복원 절차를 관리하며, 둘 다 그래프에만 해당하는 설정 없이 AgensGraph 클러스터에서 동작합니다. 서버를 둘 이상 운영한다면 손으로 쓴 `archive_command`보다 어느 쪽이든 더 나은 답입니다. {#backup-what-to-check} ## 무엇을 확인할 것인가 복원해 보지 않은 백업은 백업이 아니라 바람입니다. 특히 그래프라면, 복원 시험은 서버가 뜬다는 것 이상을 확인해야 합니다: ```cypher SET graph_path = ; MATCH (n) RETURN label(n) AS label, count(*) ORDER BY label; MATCH ()-[e]->() RETURN label(e) AS label, count(*) ORDER BY label; ``` ```sql SELECT graphname, graphmeta_valid FROM pg_catalog.ag_graph; SELECT * FROM pg_catalog.ag_property_indexes; ``` 원본과 일치하는 개수, 그리고 인덱스와 제약이 제자리에 있다는 것이 그래프가 온전히 돌아왔음을 말해 줍니다.