이 글에서는 데이터베이스 전체를 백업한 파일을 이용하여 문제가 발생한 데이터베이스를 문제가 생기기 이전 상태로 복구하는 방법을 소개합니다.
postgres사용자로 로그인
다음과 같이 PostgreSQL 권한을 가진 사용자로 로그인 합니다.
$ su - postgres
암호:*********
마지막 로그인: 수 7월 14 17:29:39 KST 2021 일시 pts/0
$ pwd
/var/lib/pgsql
PostgreSQL서버 정지하기
복구하기 전에 다음 명령으로 PostgreSQL 데이터베이스 서버를 정지합니다.
$ pg_ctl stop
서버를 멈추기 위해 기다리는 중.... 완료
서버 멈추었음
복구 대상 데이터베이스 대피하기
문제가 발생한 데이터베이스를 복구 대상의 데이터베이스를 다른 이름으로 대피 해놓습니다.
$ echo $PGDATA
/var/lib/pgsql/12/data
$ mv /var/lib/pgsql/12/data /var/lib/pgsql/12/data_bak
$ ls -la /var/lib/pgsql/12
합계 8
drwx------. 4 postgres postgres 55 7월 28 21:32 .
drwx------. 4 postgres postgres 119 7월 16 17:17 ..
drwx------. 2 postgres postgres 70 7월 28 21:28 backups
drwx------. 21 postgres postgres 4096 7월 28 21:32 data_bak
-rw-------. 1 postgres postgres 1340 7월 14 16:56 initdb.log
복구 대상 저장소 재작성하기
$ mkdir /var/lib/pgsql/12/data
$ chmod 700 /var/lib/pgsql/12/data
$ ls -la /var/lib/pgsql/12
합계 8
drwx------. 5 postgres postgres 67 7월 28 21:35 .
drwx------. 4 postgres postgres 119 7월 16 17:17 ..
drwx------. 2 postgres postgres 70 7월 28 21:28 backups
drwx------. 2 postgres postgres 6 7월 28 21:35 data
drwx------. 21 postgres postgres 4096 7월 28 21:32 data_bak
-rw-------. 1 postgres postgres 1340 7월 14 16:56 initdb.log
백업 파일로 복구하기
다음 글에서 백업한 /var/lib/pgsql/fullbackup/20210715234911/base.tar.gz 파일을 사용하여 데이터베이스를 복구합니다.
현재 복구 장소를 다음과 같이 변경한 후, 백업 파일의 압축을 풉니다.
$ cd $PGDATA
$ pwd
/var/lib/pgsql/12/data
$ tar xvfz /var/lib/pgsql/fullbackup/20210715234911/base.tar.gz
backup_label
tablespace_map
pg_wal/
./pg_wal/archive_status/
global/
global/1262
...중간 생략...
postgresql.auto.conf
pg_hba.conf
pg_ident.conf
log/
log/postgresql-Wed.log
log/postgresql-Thu.log
postgresql.conf_install
pg_hba.conf_install
pg_ident.conf_install
current_logfiles
postgresql.conf
global/pg_control
pg_wal/000000010000000000000008
pg_wal/archive_status/000000010000000000000008.done
백업했을 때의 로그 파일과 WAL파일을 삭제합니다. 참고로 WAL파일 이름은 000으로 시작합니다. $PGDATA/pg_wal에 존재하는 archive_status를 삭제하지 않도록 하려면 000에 와일드카드 문자(wildcard character) 붙여서 000으로 시작하는 파일만 삭제합니다.
$ echo $PGDATA
/var/lib/pgsql/12/data
$ rm -rf $PGDATA/log/*.log
$ rm -rf $PGDATA/pg_wal/000*
$ rm -rf $PGDATA/pg_wal/archive_status/*
삭제 결과를 다음과 같이 확인합니다.
$ ls -la $PGDATA/log
합계 4
drwx------. 2 postgres postgres 6 7월 28 22:40 .
drwx------. 20 postgres postgres 4096 7월 28 22:39 ..
$ ls -laR $PGDATA/pg_wal
/var/lib/pgsql/12/data/pg_wal:
합계 4
drwx------. 3 postgres postgres 28 7월 28 21:55 .
drwx------. 20 postgres postgres 4096 7월 28 22:39 ..
drwx------. 2 postgres postgres 6 7월 28 21:55 archive_status
/var/lib/pgsql/12/data/pg_wal/archive_status:
합계 0
drwx------. 2 postgres postgres 6 7월 28 21:55 .
drwx------. 3 postgres postgres 28 7월 28 21:55 ..
백업 파일에서 복구한 환경 파일은 오래된 내용일 수 있습니다. 다음과 같이 변경 내용이 있는지 확인합니다.
$ diff $PGDATA/postgresql.conf $PGDATA/../data_bak/postgresql.conf
$ diff $PGDATA/pg_hba.conf $PGDATA/../data_bak/pg_hba.conf
$ diff $PGDATA/pg_ident.conf $PGDATA/../data_bak/pg_ident.conf
변경 내용이 있다면 환경 파일을 다음과 같이 대피했던 원래의 상태로 돌려 놓습니다.
$ cp -p $PGDATA/../data_bak/postgresql.conf $PGDATA/postgresql.conf
$ cp -p $PGDATA/../data_bak/pg_hba.conf $PGDATA/pg_hba.conf
$ cp -p $PGDATA/../data_bak/pg_ident.conf $PGDATA/pg_ident.conf
백업 시 WAL파일의 최종 위치 확인하기
백업할 때의 WAL파일 위치를 확인할 수 있습니다.
$ cat $PGDATA/backup_label
START WAL LOCATION: 0/8000028 (file 000000010000000000000008)
CHECKPOINT LOCATION: 0/8000060
BACKUP METHOD: streamed
BACKUP FROM: master
START TIME: 2021-07-15 23:52:35 KST
LABEL: pg_basebackup base backup
START TIMELINE: 1
복구 대상 WAL파일 확인
위의 “백업 시의 WAL파일의 최종 위치 확인하기“ 에서 확인한 WAL위치 이후의 WAL파일이 존재한다면 복구 대상이 됩니다. 전제 조건으로 postgresql.conf 환경 파일의 restore_command에 다음과 같이 명령을 지정해야 합니다.
$ vi /var/lib/pgsql/12/data/postgresql.conf
... 중간 생략 ...
restore_command = 'cp /var/lib/pgsql/12/backups/%f %p'
... 중간 생략 ...
다음 명령으로 복구 대상 WAL파일의 존재 여부를 확인합니다.
$ ls -la /var/lib/pgsql/12/backups
복구 시작 알림 파일 작성하기
다음과 같이 복구를 알리는 파일을 만듭니다.
$ touch $PGDATA/recovery.signal
PostgreSQL서버 기동하기
다음 명령으로 서버를 기동합니다.
$ pg_ctl start
서버를 시작하기 위해 기다리는 중....2021-07-28 23:33:16.227 KST [2613] 로그: starting PostgreSQL 12.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
2021-07-28 23:33:16.229 KST [2613] 로그: IPv6, 주소: "::1", 포트 5432 번으로 접속을 허용합니다
2021-07-28 23:33:16.229 KST [2613] 로그: IPv4, 주소: "127.0.0.1", 포트 5432 번으로 접속을 허용합니다
2021-07-28 23:33:16.230 KST [2613] 로그: "/var/run/postgresql/.s.PGSQL.5432" 유닉스 도메인 소켓으로 접속을 허용합니다
2021-07-28 23:33:16.232 KST [2613] 로그: "/tmp/.s.PGSQL.5432" 유닉스 도메인 소켓으로 접속을 허용합니다
2021-07-28 23:33:16.245 KST [2613] 로그: 서버 로그를 로그 수집 프로세스로 보냅니다.
2021-07-28 23:33:16.245 KST [2613] 힌트: 이제부터 서버 로그는 "log" 디렉터리에 보관됩니다.
완료
서버 시작됨
$ cat $PGDATA/log/*.log
2021-07-28 23:33:16.249 KST [2615] 로그: 데이터베이스 시스템이 비정상적으로 종료되었음; 마지막 운영시간: 2021-07-15 23:52:35 KST
cp: cannot stat `/var/lib/pgsql/12/backups/00000002.history': 그런 파일이나 디렉터리가 없습니다
2021-07-28 23:33:16.271 KST [2615] 로그: 아카이브 복구 작업을 시작합니다
cp: cannot stat `/var/lib/pgsql/12/backups/000000010000000000000008': 그런 파일이나 디렉터리가 없습니다
2021-07-28 23:33:16.279 KST [2615] 로그: 0/8000028에서 redo 작업 시작됨
2021-07-28 23:33:16.282 KST [2615] 로그: 0/8000138 위치에서 복구 일관성을 맞춤
2021-07-28 23:33:16.283 KST [2613] 로그: 데이터베이스 시스템이 읽기 전용으로 연결을 수락할 준비가 되었습니다.
cp: cannot stat `/var/lib/pgsql/12/backups/000000010000000000000009': 그런 파일이나 디렉터리가 없습니다
2021-07-28 23:33:16.293 KST [2615] 로그: 0/8000138에서 redo 작업 완료
cp: cannot stat `/var/lib/pgsql/12/backups/000000010000000000000008': 그런 파일이나 디렉터리가 없습니다
cp: cannot stat `/var/lib/pgsql/12/backups/00000002.history': 그런 파일이나 디렉터리가 없습니다
2021-07-28 23:33:16.305 KST [2615] 로그: 지정한 새 타임라인 ID: 2
2021-07-28 23:33:16.348 KST [2615] 로그: 아카이브 복구 완료
cp: cannot stat `/var/lib/pgsql/12/backups/00000001.history': 그런 파일이나 디렉터리가 없습니다
2021-07-28 23:33:16.362 KST [2613] 로그: 이제 데이터베이스 서버로 접속할 수 있습니다
서버 시작됨
$ ps aux | grep "postgres:" | grep -v "\(root\|grep\)"
복구에 실패하는 경우
다음은 복구에 실패하는 경우입니다.
postgresql.conf 환경 파일의 restore_command 를 지정하지 않고 복구하는 경우
$ pg_ctl start
서버를 시작하기 위해 기다리는 중....2021-07-28 23:00:54.127 KST [2345] 로그: starting PostgreSQL 12.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
2021-07-28 23:00:54.128 KST [2345] 로그: IPv6, 주소: "::1", 포트 5432 번으로 접속을 허용합니다
2021-07-28 23:00:54.128 KST [2345] 로그: IPv4, 주소: "127.0.0.1", 포트 5432 번 으로 접속을 허용합니다
2021-07-28 23:00:54.130 KST [2345] 로그: "/var/run/postgresql/.s.PGSQL.5432" 유닉스 도메인 소켓으로 접속을 허용합니다
2021-07-28 23:00:54.132 KST [2345] 로그: "/tmp/.s.PGSQL.5432" 유닉스 도메인 소 켓으로 접속을 허용합니다
2021-07-28 23:00:54.142 KST [2345] 로그: 서버 로그를 로그 수집 프로세스로 보냅 니다.
2021-07-28 23:00:54.142 KST [2345] 힌트: 이제부터 서버 로그는 "log" 디렉터리에 보관됩니다.
중지 기다리는 중
pg_ctl: 서버를 시작 할 수 없음
로그 출력을 살펴보십시오.
$ cat $PGDATA/log/*.log
2021-07-28 23:00:54.147 KST [2347] 로그: 데이터베이스 시스템이 비정상적으로 종 료되었음; 마지막 운영시간: 2021-07-15 23:52:35 KST
2021-07-28 23:00:54.168 KST [2347] 치명적오류: 대기 모드를 활성화 하지 않았다면(standby_mode = off), restore_command 설정은 반드시 있어야 함
2021-07-28 23:00:54.170 KST [2345] 로그: 시작 프로세스 (PID 2347) 프로그램은 1 코드로 마쳤습니다
2021-07-28 23:00:54.170 KST [2345] 로그: 시작 프로세스 실패 때문에 서버 시작이 중지 되었습니다
2021-07-28 23:00:54.171 KST [2345] 로그: 데이터베이스 시스템 서비스를 중지했습 니다
postgresql.conf의 max_wal_senders의 설정 값이 낮게 설정되어있는 경우
$ cat $PGDATA/log/*.log
2021-07-28 22:52:57.969 KST [2283] 로그: 데이터베이스 시스템이 비정상적으로 종료되었음; 마지막 운영시간: 2021-07-15 23:52:35 KST
cp: cannot stat `/var/lib/pgsql/12/backups/00000002.history': 그런 파일이나 디렉터리가 없습니다
2021-07-28 22:52:57.991 KST [2283] 로그: 아카이브 복구 작업을 시작합니다
cp: cannot stat `/var/lib/pgsql/12/backups/000000010000000000000008': 그런 파일이나 디렉터리가 없습니다
2021-07-28 22:52:57.997 KST [2283] 치명적오류: 읽기 전용 대기 서버로 운영이 불가능합니다. 현재 max_wal_senders = 1 설정은 주 서버의 설정값(10)보다 낮게 설정 되어 있기 때문입니다.
2021-07-28 22:52:57.999 KST [2281] 로그: 시작 프로세스 (PID 2283) 프로그램은 1 코드로 마쳤습니다
2021-07-28 22:52:57.999 KST [2281] 로그: 시작 프로세스 실패 때문에 서버 시작이 중지 되었습니다
2021-07-28 22:52:58.000 KST [2281] 로그: 데이터베이스 시스템 서비스를 중지했습니다
/var/lib/pgsql/12/data/backup_label 에서 정의된 요청된 체크포인트 레코드의 위치의 파일이 $PGDATA/pg_wal 또는 /var/lib/pgsql/12/backups/ 의 어디에도 존재하지 않는 경우
$ pg_ctl start
서버를 시작하기 위해 기다리는 중....2021-07-28 23:11:03.819 KST [2416] 로그: starting PostgreSQL 12.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
2021-07-28 23:11:03.820 KST [2416] 로그: IPv6, 주소: "::1", 포트 5432 번으로 접속을 허용합니다
2021-07-28 23:11:03.820 KST [2416] 로그: IPv4, 주소: "127.0.0.1", 포트 5432 번으로 접속을 허용합니다
2021-07-28 23:11:03.821 KST [2416] 로그: "/var/run/postgresql/.s.PGSQL.5432" 유닉스 도메인 소켓으로 접속을 허용합니다
2021-07-28 23:11:03.825 KST [2416] 로그: "/tmp/.s.PGSQL.5432" 유닉스 도메인 소켓으로 접속을 허용합니다
2021-07-28 23:11:03.838 KST [2416] 로그: 서버 로그를 로그 수집 프로세스로 보냅니다.
2021-07-28 23:11:03.838 KST [2416] 힌트: 이제부터 서버 로그는 "log" 디렉터리에 보관됩니다.
중지 기다리는 중
pg_ctl: 서버를 시작 할 수 없음
로그 출력을 살펴보십시오.
$ cat $PGDATA/log/*.log
2021-07-28 23:11:03.844 KST [2418] 로그: 데이터베이스 시스템이 비정상적으로 종료되었음; 마지막 운영시간: 2021-07-15 23:52:35 KST
2021-07-28 23:11:03.867 KST [2418] 로그: 아카이브에서 "00000002.history" 로그파일을 복구했음
cp: cannot stat `/var/lib/pgsql/12/backups/00000003.history': 그런 파일이나 디렉터리가 없습니다
2021-07-28 23:11:03.871 KST [2418] 로그: 아카이브 복구 작업을 시작합니다
2021-07-28 23:11:03.875 KST [2418] 로그: 아카이브에서 "00000002.history" 로그파일을 복구했음
cp: cannot stat `/var/lib/pgsql/12/backups/000000010000000000000008': 그런 파일이나 디렉터리가 없습니다
2021-07-28 23:11:03.881 KST [2418] 로그: 잘못된 checkpoint 레코드
2021-07-28 23:11:03.881 KST [2418] 치명적오류: 요청된 체크포인트 레코드의 위치를 바르게 잡을 수 없음
2021-07-28 23:11:03.881 KST [2418] 힌트: If you are restoring from a backup, touch "/var/lib/pgsql/12/data/recovery.signal" and add required recovery options.
If you are not restoring from a backup, try removing the file "/var/lib/pgsql/12/data/backup_label".
Be careful: removing "/var/lib/pgsql/12/data/backup_label" will result in a corrupt cluster if restoring from a backup.
2021-07-28 23:11:03.882 KST [2416] 로그: 시작 프로세스 (PID 2418) 프로그램은 1 코드로 마쳤습니다
2021-07-28 23:11:03.882 KST [2416] 로그: 시작 프로세스 실패 때문에 서버 시작이 중지 되었습니다
2021-07-28 23:11:03.884 KST [2416] 로그: 데이터베이스 시스템 서비스를 중지했습니다
backup을 복구해서 바로 시작한 경우
$ pg_ctl start
서버를 시작하기 위해 기다리는 중....2021-07-28 23:19:47.028 KST [2471] 로그: starting PostgreSQL 12.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
2021-07-28 23:19:47.029 KST [2471] 로그: IPv6, 주소: "::1", 포트 5432 번으로 접속을 허용합니다
2021-07-28 23:19:47.029 KST [2471] 로그: IPv4, 주소: "127.0.0.1", 포트 5432 번으로 접속을 허용합니다
2021-07-28 23:19:47.030 KST [2471] 로그: "/var/run/postgresql/.s.PGSQL.5432" 유닉스 도메인 소켓으로 접속을 허용합니다
2021-07-28 23:19:47.032 KST [2471] 로그: "/tmp/.s.PGSQL.5432" 유닉스 도메인 소켓으로 접속을 허용합니다
2021-07-28 23:19:47.053 KST [2471] 로그: 서버 로그를 로그 수집 프로세스로 보냅니다.
2021-07-28 23:19:47.053 KST [2471] 힌트: 이제부터 서버 로그는 "log" 디렉터리에 보관됩니다.
완료
서버 시작됨
$ cd log
$ ls
1.log 2.log postgresql-Wed.log
$ cat postgresql-Wed.log
2021-07-28 23:19:47.069 KST [2473] 로그: 데이터베이스 시스템이 비정상적으로 종료되었음; 마지막 운영시간: 2021-07-15 23:52:35 KST
2021-07-28 23:19:47.091 KST [2473] 로그: 0/8000028에서 redo 작업 시작됨
2021-07-28 23:19:47.091 KST [2473] 로그: 0/8000138 위치에서 복구 일관성을 맞춤
2021-07-28 23:19:47.092 KST [2473] 로그: 0/8000138에서 redo 작업 완료
2021-07-28 23:19:47.135 KST [2471] 로그: 이제 데이터베이스 서버로 접속할 수 있습니다