백업 및 복구
다른 데이터베이스 시스템과 마찬가지로 AgensGraph에서도 백업은 매우 중요합니다. 일반적으로 서비스에 중요한 데이터 대부분이 데이터베이스에 저장되기 때문입니다. 백업 및 복원 과정은 비교적 간단하며, 더 나은 이해를 돕기 위해 이 과정의 기술적, 개념적 측면을 설명합니다. AgensGraph는 PostgreSQL을 기반으로 개발되었으므로, RDB(GDB가 아닌) 측의 기능을 소개할 때는 PostgreSQL 기술 문서를 인용하였습니다.
이 장에서는 파일 시스템 기반 백업과 아카이브 모드 백업에 대해 설명합니다.
백업
파일 시스템 수준 백업
이는 전체 데이터 저장 공간을 직접 복사하여 파일 시스템 수준에서 백업하는 방식입니다. 일반적인 운영체제에서 수행하는 파일 시스템 백업과 크게 다르지 않습니다. 예를 들면 다음과 같습니다.
tar -cf backup.tar /usr/local/pgsql/data
위 명령으로 백업이 가능합니다. 그러나 이 방식에는 다음과 같은 두 가지 제약이 있어, 실제로는 pg_dump 명령을 사용하는 것보다 유용성이 떨어집니다.
정상적인 백업 작업을 위해서는 데이터베이스 서버를 중지해야 합니다. 모든 클라이언트 연결을 차단하고 파일 시스템을 복사하는 것만으로는 안전한 백업을 보장하지 못합니다. (tar 명령이나 그와 유사한 다른 도구들은 파일 시스템 상태에 대한 일관된 스냅샷을 제공하지 못하며, 서버가 사용하는 내부 버퍼링 정보를 정확하게 반영할 수 없기 때문입니다.) 마찬가지로 복원할 때에도 서버는 중지된 상태여야 합니다.
데이터베이스 내 여러 파일의 위치와 용도를 잘 알고 있다면, 개별 데이터베이스나 테이블에 해당하는 파일만 복사하여 사용할 수 있다고 생각할 수 있습니다. 설령 그렇다 하더라도 커밋 로그 파일 없이는 정상적인 운영이 불가능합니다. pg_clog/* 파일은 모든 트랜잭션의 커밋 상태를 저장합니다. 이 로그 파일들은 테이블 단위가 아니라 데이터베이스 클러스터 단위로 처리되므로 부분 복사가 불가능하며, 개별 테이블의 물리 파일과 로그 파일을 복사하더라도 다른 테이블과 관련되어 있을 수 있습니다.
파일 시스템 기반 백업에서 고려해야 할 또 다른 사항은, 파일 시스템이 “일관된(그리고 신뢰할 수 있는) 스냅샷” 기능을 제공하는 경우 그 기능을 사용할 때 주의해야 한다는 점입니다. 파일 시스템 스냅샷 기능을 사용하는 일반적인 백업 방법은 다음과 같습니다. i) “고정 스냅샷(frozen snapshot)”을 생성하고, ii) 모든 데이터 클러스터 파일을 복사한 다음(앞서 언급했듯이 부분 파일을 백업하는 것은 의미가 없습니다), iii) 잠긴 스냅샷의 잠금을 해제합니다. 파일 시스템이 이 기능을 제공한다면 데이터베이스 서버가 실행 중인 상태에서도 백업이 가능합니다. 이때 백업은 운영 중에 수행되므로, 데이터베이스 서버를 정상적으로 종료하지 않은 상태로 데이터베이스 파일이 저장됩니다. 백업 데이터로 데이터베이스 서버를 시작하면, 서버는 이전 서버를 충돌 상태로 인식하고 WAL 로그를 재실행합니다. 그러나 시작 전에 CHECKPOINT 명령을 실행하고 백업 작업 중에 생성된 WAL 로그를 별도로 보관하면, 큰 문제 없이 실행됩니다. (물론 WAL 로그를 무시할 수도 있습니다.)
문제는 데이터베이스 서버가 여러 파일 시스템을 사용하는 경우입니다. 예를 들어 서로 다른 파티션을 사용하는 테이블스페이스를 생성한 경우, 데이터베이스 서버가 사용하는 모든 파일 시스템의 “고정 스냅샷”을 동시에 생성할 수 있어야 합니다. 이러한 방식으로 백업을 생성하려면 파일 시스템 문서를 주의 깊게 읽고, 이점과 그에 따르는 위험을 충분히 따져본 후 백업을 수행하시기 바랍니다.
여러 파일 시스템 스냅샷을 동시에 생성할 수 없다면, 스냅샷을 생성하는 동안 데이터베이스 서버를 중지해야 합니다. 또 다른 방법은 rsync 애플리케이션을 사용하는 것입니다. 작업은 두 단계로 진행됩니다. 서버가 실행 중일 때 먼저 모든 데이터를 동기화합니다. 그런 다음 서버를 중지하고 다시 한 번 데이터를 동기화합니다. 서버가 중지된 동안에는 변경된 파일만 동기화되므로 서버 다운타임을 최소화할 수 있습니다.
파일 시스템 백업은 일반적으로 SQL 덤프보다 더 많은 백업 공간을 필요로 합니다. (pg_dump로 생성된 덤프 파일에는 물리적으로 인덱스가 없으며, 인덱스를 생성하는 명령만 포함되어 있기 때문입니다.) 이러한 이유로 복원 작업은 파일 시스템 백업에서 훨씬 더 빠르게 수행될 수 있습니다.
아카이브 모드 백업
Write Ahead Logging(WAL) 아카이브 생성
내부적으로 AgensGraph 시스템은 데이터베이스를 조작하는 과정에서 끊임없이 WAL 레코드를 생성합니다. 이러한 레코드는 물리 디스크 공간에 저장될 수 있도록 WAL 세그먼트 파일로 분할됩니다. 단일 WAL 파일은 기본적으로 16MB 파일입니다(이 크기는 서버를 컴파일할 때 결정됩니다). 파일명에는 WAL 순서에 해당하는 번호가 사용됩니다. WAL 아카이브 파일을 생성하지 않도록 설정하면 이러한 파일이 몇 개만 생성되며, 더 이상 사용하지 않는 로그 파일을 찾아 “재사용”해야 합니다. 내부적으로는 WAL 레코드의 상태 정보를 찾아, 체크포인트 작업을 통해 더 이상 사용하지 않는 상태로 변경하고 그 자리에 새로운 WAL 레코드를 기록함으로써 재사용합니다.
WAL 아카이브 파일을 생성하면, 특정 WAL 세그먼트 파일을 재사용하기 전에 기존 WAL 레코드 정보를 다른 곳(동일 호스트, NFS 마운트 지점, 또는 테이프 등)에 아카이브합니다. 아카이브 방식은 관리자가 직접 지정합니다. 이미 동일한 이름의 파일이 존재하는 경우조차도 관리자가 결정하도록 합니다. 다만 WAL 세그먼트 파일을 재사용할 때, AgensGraph 서버는 관리자가 설정한 “아카이브 방식”에 따라서만 작업을 수행합니다. 아카이브를 위해 단순히 cp 명령을 사용할 수도 있고, 더 복잡한 사용자 정의 셸 스크립트를 사용할 수도 있으며, 백업 솔루션 명령을 사용할 수도 있습니다. 이 부분은 전적으로 관리자에게 달려 있습니다.
WAL 아카이브 파일을 생성하려면 설정 매개변수 wal level의 값으로 archive(또는 hot_standby)를 지정합니다. 다음으로 환경 설정 매개변수 archive mode를 on으로 설정하고, 환경 설정 매개변수 archive command를 적절한 시스템 명령으로 설정합니다. 이 모든 설정은 postgresql.conf 파일에서 구성합니다. archive_command 값으로 지정할 셸 명령에는 %p(WAL 로그 파일의 절대 경로)와 %f(아카이브할 로그 파일의 이름) 예약 인자를 사용할 수 있습니다. %를 문자 그대로 입력해야 하는 경우에는 %%를 입력합니다. 일반적으로 이 설정은 다음과 같은 형식으로 사용합니다.
# Unix
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
# Windows
archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"'
위 설정은 단순히 WAL 세그먼트 파일을 /mnt/server/archivedir 디렉터리에 (동일한 파일명으로) 복사합니다. 위 내용은 Unix 및 Windows 운영체제에 대한 예시일 뿐입니다. 실제 설정은 운영체제에 맞게 변경해야 합니다. %p %f 예약 인자는 명령을 실제로 실행할 때 다음과 같이 변경됩니다.
test ! -f /mnt/server/archivedir/00000001000000A900000065 &&
cp pg_xlog/00000001000000A900000065\ /mnt/server/archivedir/00000001000000A900000065
이렇게 하면 항상 특정 위치에 최신 WAL 로그 파일을 유지할 수 있습니다.
이 아카이브 명령은 AgensGraph 서버를 실행한 시스템 사용자의 권한으로 실행됩니다. 따라서 WAL 세그먼트 파일을 처리할 때와 마찬가지로, 아카이브 파일을 처리할 때에도 보안 정책을 고려해야 합니다. 누구나 읽고, 덮어쓰고, 삭제할 수 있다면 치명적인 보안 사고가 발생할 수 있다는 점에 유의해야 합니다.
또 한 가지 유의할 점은, 아카이브 명령의 셸 실행 반환값이 명령이 성공하면 0(zero)이어야 하고, 명령이 실패하면 다른 값이어야 한다는 것입니다. 서버는 이 반환값으로 로그 파일이 성공적으로 아카이브되었는지 실패했는지를 판단하며, 성공한 경우 원본 로그 파일을 삭제하거나 재사용하고, 실패한 경우 성공할 때까지 재시도합니다.
이 아카이브 명령으로 이미 존재하는 파일을 덮어써서는 안 됩니다. 덮어쓰면 복원 작업에서 의도하지 않은 오류가 발생할 수 있습니다. (이 파일은 이미 다른 데이터베이스에 의해 생성되었거나 사용되었을 수 있습니다.) 이미 존재할 경우 지속적으로 오류가 발생할 수 있으므로, 관리자가 로그 파일을 수동으로 처리하는 것이 가장 안전합니다.
로그 파일을 아카이브하기 전에 파일이 이미 존재하는지 확인하는 것이 좋습니다. 존재한다면 명령이 0이 아닌 값을 반환하도록 설정합니다. Unix에서는 이 작업을 위해 test 명령을 제공합니다. 일부 Unix 플랫폼에서는 이미 존재하는 파일을 덮어쓰지 않도록 cp 명령에 -i 옵션을 제공합니다. 이 명령을 사용할 때는 반드시 반환값을 확인해야 합니다. (GNU cp 명령은 로그 파일이 존재하면 “0”을 반환하는데, 이는 바람직하지 않습니다.)
WAL 파일을 별도로 저장할 때, 운영 작업을 수동으로 중단해야 하거나 저장 공간 부족으로 저장 작업이 반복적으로 실패할 수 있습니다. 예를 들어 WAL 세그먼트 파일을 테이프 저장 장치에 아카이브하려는데 해당 장치가 테이프를 자동으로 교체하지 않고 테이프에 여유 공간이 없는 경우, 사용자는 오류가 발생할 때까지 파일 쓰기 작업을 계속 실행하며 이 과정을 반복할 수 있습니다. 이러한 경우 데이터가 테이프 저장 장치에 안전하게 복사되지 않았으므로 pg_xlog/ 디렉터리는 WAL 세그먼트 파일을 삭제하거나 재사용하지 않으며, 이후 생성되는 새 WAL 세그먼트 파일이 계속 쌓이다가 결국 pg_xlog/ 디렉터리에 더 이상 여유 공간이 없어 멈추고 서버에서 PANIC 오류가 발생합니다.
WAL 파일을 별도로 저장할 때는 WAL 파일의 데이터 기록 속도도 고려해야 합니다. 작업이 제대로 수행되더라도, WAL 파일이 생성되는 속도가 파일을 별도로 보관하는 속도보다 빠르면 동일한 문제가 발생할 수 있습니다. 물론 pg_xlog/ 디렉터리에 충분한 여유 공간이 있다면 문제가 되지 않습니다. 이 기능을 사용하기 전에 이 절에서 다룬 이러한 문제를 충분히 고려해야 하며, 관리자는 이 기능이 의도한 대로 작동하는지 모니터링해야 합니다.
저장 파일의 경로는 최대 64개의 ASCII 문자여야 합니다. 파일명에는 반드시 예약어 %f를 사용해야 합니다(즉, 디렉터리만 변경할 수 있습니다). 원본 WAL 세그먼트 파일에는 반드시 예약어 %p를 사용해야 합니다.
WAL 파일에는 트랜잭션 작업 정보만 포함되어 있으므로, 이 백업 방법으로 복원되는 데이터베이스에는 postgresql.conf, pg_hba.conf, pg_ident.conf 파일의 변경 사항이 반영되지 않는다는 점에 유의하시기 바랍니다. 이러한 설정 파일은 시스템의 일반 파일 백업 정책에 따라 백업해야 합니다.
아카이브 명령은 WAL 파일 중에서 서버에 모두 반영된(롤백되거나 커밋된 후 체크포인트된) 파일에 대해 실행됩니다. 즉, 워크로드가 매우 적은 데이터베이스의 경우 아카이브 명령이 실행되는 간격이 매우 깁니다. 이 간격 동안 데이터베이스 장애가 발생하면 데이터 손실이 발생합니다. 따라서 WAL 세그먼트 파일의 모든 내용이 처리되기 전이라도 일정 시간이 지나면 아카이브 명령을 강제로 사용하여 이 세그먼트 파일을 별도로 저장해야 합니다. 설정값이 너무 짧으면 디스크 공간이 낭비될 수 있습니다(단점). 일반적으로 분 단위 설정이 적절합니다.
또한 pg_switch_xlog 함수를 사용하여 사용자가 세그먼트 파일을 강제로 변경하도록 할 수도 있습니다. 이 함수는 일반적으로 대량의 데이터 입력, 수정 또는 삭제가 발생하여 즉각적인 백업이 필요할 때 사용합니다.
wal_level 값을 minimal로 설정하면 이 WAL 로그를 저장하고 이를 기반으로 복원할 수 없습니다. 이 설정을 사용하면 복원과 관련된 정보를 WAL 파일에 보관하지 않기 때문입니다. 따라서 wal_level 설정을 변경할 때는 서버를 재시작해야 합니다. 다만 archive_command 설정의 경우에는 설정 파일을 다시 로드하는 것으로 충분합니다. 운영 중에 이 작업을 중지해야 할 수도 있습니다. 그렇게 하려면 archive_command 설정을 빈 문자열(‘’)로 지정합니다. archive_command 설정은 WAL 파일을 다시 복사할 때까지 pg_xlog/ 디렉터리에 유지됩니다.
복구
연속 아카이브 백업을 사용한 복구
문제가 발생했을 때 아카이브 모드 백업 방법으로 아카이브된 백업을 사용하여 데이터베이스 서버를 복구하는 방법을 설명합니다. 작업 순서는 다음과 같습니다.
서버가 실행 중이면 먼저 서버를 중지합니다.
시스템에 충분한 디스크 공간이 있다면, 전체 데이터베이스 클러스터 디렉터리, 관련된 사용자 정의 테이블스페이스 파일, 그리고 필요한 모든 WAL 세그먼트 파일을 임시 위치에 복사합니다. 이미 실행 중인 시스템에서 이 작업을 수행하려면 최소한 두 배의 디스크 공간이 필요합니다. 그러한 여유 공간이 없다면, 적어도 기존 데이터베이스 서버의 클러스터 디렉터리에 있는 pg_xlog 파일과 서버 설정 파일은 저장합니다. 백업된 WAL 세그먼트 파일과 백업되지 않은 WAL 세그먼트 파일을 함께 저장하면, 서버가 중지되기 직전 상태로 복원할 수 있습니다.
기존 서버의 데이터 클러스터 디렉터리와 기존 테이블스페이스 디렉터리를 모두 삭제합니다.
백업 파일을 원래 위치에 복사합니다. 이때 사용자는 데이터베이스 서버를 실행하는 시스템 사용자여야 합니다. (root로 작업하는 경우 반드시 소유자로 변경해야 합니다!) 따라서 파일 접근 권한과 소유자를 시스템 사용자에 맞게 설정해야 합니다. 사용자 정의 테이블스페이스를 사용하는 경우, 소스 디렉터리와 그 안에 있는 파일 중 pg_tblspc/ 디렉터리에 심볼릭 링크로 되어 있는 파일을 복사합니다.
pg_xlog/디렉터리는 비워 둡니다. 이 디렉터리에 파일이 있다면 모두 제거해야 합니다. 복구 과정에서 필요한 파일은 이 디렉터리에 자동으로 생성됩니다. 백업에서pg_xlog/디렉터리를 제외했다면, 데이터베이스 서버가 사용할 수 있도록 디렉터리 또는 심볼릭 링크를 생성합니다. 이때에도 디렉터리 권한과 소유자가 데이터베이스 서버를 실행하는 시스템 사용자에게만 허용되는지 확인해야 합니다. 심볼릭 링크인 경우, 이전 데이터를 덮어쓸 수 있도록 이전 데이터베이스에서 사용한 소스 경로와 동일한지 반드시 확인해야 합니다.WAL 세그먼트 파일의 백업본이 없다면, 2단계에서 복사한 pg_xlog/ 파일을 복원하려는 위치에 복사합니다. (이동이 아니라 복사하는 것이 권장됩니다. 복구가 아직 완료되지 않았으므로 복사하는 것이 안전합니다.)
데이터베이스 클러스터 디렉터리에 recovery.conf를 생성합니다. 복구 과정 중 외부에서 접근할 수 없도록 pg_hba.conf를 임시로 수정하는 것도 좋습니다.
서버를 실행합니다. 서버는 복구 모드로 실행되어 필요한 WAL 파일을 찾고, 복구되지 않은 트랜잭션을 일괄적으로 처리하기 시작합니다. 복구 작업 중 외부 영향으로 서버가 멈추면, 서버를 다시 시작하여 복구 작업을 계속하면 됩니다. 복구 과정이 끝나면 서버는 recovery.conf의 이름을 recovery.done으로 변경하고, 정상 실행 상태에서 클라이언트의 연결을 기다립니다. 이는 복구 모드로 다시 실행되는 것을 방지하기 위함입니다.
이제 데이터베이스에 연결하여 데이터가 정상인지 확인합니다. 정상이 아니라면 서버 로그를 검토하고 1단계로 돌아갑니다. 모든 데이터와 데이터베이스 상태가 정상이라면 pg_hba.conf의 내용을 수정하여 외부 접근을 허용합니다.
이 복구 방법의 핵심은 백업된 WAL 세그먼트 파일을 데이터베이스에 어떻게 적용할 것인지, 그리고 어느 시점까지 복원할 것인지입니다. 이는 recovery.conf에 지정합니다. 이 파일을 생성하는 간단한 방법은, 먼저 데이터베이스 배포본의 share/ 디렉터리에 있는 recovery.conf.sample을 복사한 후 필요한 부분만 수정하는 것입니다. recovery.conf의 핵심 부분은 restore_command입니다. 이 설정은 AgensGraph에서 백업된 WAL 세그먼트 파일을 어떻게 적용할지에 대한 정의입니다. 간단히 말해, 서버 환경 설정의 archive_command와 반대되는 명령을 지정할 수 있습니다. 여기서 사용하는 예약어는 archive_command 설정값을 지정할 때와 동일합니다. %f 값은 백업 아카이브 디렉터리의 파일명이고, %p 값은 트랜잭션 로그 파일로 대체됩니다. (상대 경로를 사용하는 경우, 서버가 실행 중인 현재 디렉터리를 기준으로 처리됩니다.) 예약어 %%는 % 문자로 처리됩니다. 다음은 일반적인 설정입니다.
restore_command = 'cp /mnt/server/archivedir/%f %p'
위 설정은 /mnt/server/archivedir 디렉터리에 이전에 백업된 WAL 세그먼트 파일을 복원하는 데 사용됩니다. 물론 사용하는 백업 장치에 따라 이 명령은 훨씬 더 복잡해질 수 있습니다. 일부 명령을 직접 포함하는 셸 스크립트를 작성하여 사용할 수도 있습니다(예: 테이프 백업 장치처럼 테이프를 마운트하여 원하는 위치로 이동하는 경우). 여기서 중요한 점은, 여기에 지정된 작업이 실패하면 작업의 반환값이 0이 아니어야 한다는 것입니다. 이 작업은 아카이브 백업 디렉터리에 없는 파일도 요청합니다. 이 작업의 결과는 0이 아닌 반환값을 반환해야 합니다(이는 오류가 아닙니다). 스크립트에 명령이 없거나, 서버가 정상적으로 종료되어 (복구 과정의 일부로서) SIGTERM 시그널이 아닌 다른 시그널이 작업을 중지시킨 경우, 이는 오류로 간주됩니다. 이러한 상황에서는 복구 작업이 중지되고 서버도 작동을 멈춥니다.
서버는 .backup 또는 .history로 끝나는 파일을 찾을 수 있습니다. 서버가 찾는 파일이 없는 경우, 해당 파일이 존재하지 않는다는 것을 (0이 아닌 값을 반환하여) 서버에 알려야 합니다. %f 파일명과 서버로 복사된 %p 파일명이 항상 같은 것은 아닙니다. 이러한 이유로, 직접 셸 스크립트를 작성하여 사용할 때는 이 부분을 처리하면서 실수하지 않도록 주의해야 합니다.
아카이브 백업 디렉터리에서 WAL 세그먼트 파일을 찾을 수 없는 경우, 데이터 클러스터 내부의 pg_xlog/ 디렉터리를 찾아봅니다. 처리해야 할 WAL 세그먼트 파일이 더 있다면, 백업되지 않은 파일이라도 처리됩니다. 그러나 동일한 파일명의 파일이 아카이브 백업 디렉터리에 이미 존재하는 경우에는 해당 파일이 적용되고, pg_xlog/의 파일은 무시되며, 새로운 WAL 세그먼트 이름이 그 로그를 반영합니다. 이러한 이유로 복구 과정 전에 WAL 세그먼트 파일을 정리해야 합니다.
일반적으로 복구 작업은 아카이브 백업 디렉터리의 마지막 로그 파일을 반영합니다. 다음 파일이 없을 때까지 찾으므로, 복구 로그의 마지막에는 “file not found” 메시지가 출력됩니다. 복구 과정을 시작할 때 00000001.history 파일도 찾을 수 있습니다. 이 모든 것은 정상적인 복구 과정에서 발생하는 로그입니다.
recovery.conf에 복구 중지 지점을 지정하여 복구 작업을 원하는 시점에서 중지할 수도 있습니다. 이 지점을 “복구 대상(recovery target)”이라고 합니다. 이 기능은 미숙한 데이터베이스 관리자가 실수로 중요한 테이블을 삭제하는 등의 운영 오류로부터 복구하는 데 도움이 되므로 유용합니다. “복구 대상”은 특정 시간으로 지정할 수도 있고, 관리자가 지정한 임의의 문자열로 지정할 수도 있습니다. 또한 특정 트랜잭션 ID로 지정할 수도 있습니다. 사고가 발생한 트랜잭션 ID를 도구로 확인할 수 없는 경우에는, 복구를 위해 단순히 특정 시간이나 관리자가 미리 정의한 문자열을 지정하면 됩니다.
복구가 중지되는 지점은 베이스 백업 시간 이후여야 합니다. pg_stop_backup 명령이 실행된 시간보다 나중으로 지정해야 합니다. 베이스 백업을 사용하여 데이터 클러스터 파일을 파일 시스템 수준으로 백업하고 백업된 시점으로 복원할 수는 없습니다. 이 작업이 필요하다면, 이전 베이스 백업 데이터와 그에 해당하는 WAL 백업 파일이 필요합니다.
WAL 파일 자체에 문제가 있는 경우, 정상적으로 처리된 트랜잭션에만 적용되며 복구 작업과 서버가 모두 중지됩니다. 이 경우 문제가 발생한 시점을 파악하여 처음부터 “복구 대상” 지점까지 복원해야 합니다. 복구 작업 중 외부 영향으로 작업이 중지된 경우에는 문제의 원인을 해결해야 합니다. 그런 다음 서버를 다시 실행하여 복구 과정을 계속하면 됩니다. 복구 작업은 정상 실행 환경에서 체크포인트 작업과 함께 다시 실행됩니다. 내부적으로 pg_control 파일이 주기적으로 갱신되며, 이미 반영된 로그는 더 이상 다시 처리되지 않습니다. 즉, 중복 처리를 걱정할 필요가 없습니다.