PostgreSQL에서 특정 테이블에 대한 잘못된 조작으로 특정 시점으로 다시 되돌아가야한다면, 일반적으로 pg_dump를 이용한 주기적인 덤프 파일을 이용해서 복구하거나, archive_mode 기능을 on 으로 설정해서 online 백업을 받았던 베이스 백업과 그 트랜잭션 로그 쪼가리 파일을 가지고, 전체 데이터클러스터를 새로운 서버로 실행 한 뒤, 해당 테이블을 빼내서 운영 DB로 옮기는 방식을 택합니다.
이 부분에 대한 빠른 부분 복구를 어떻게 할 수 있을까?
이것이 이 글의 내용입니다.
0. PostgreSQL에서의 recovery mode 특징
PostgreSQL은 recovery.conf 파일이 $PGDATA 디렉토리내에 있다면, DB가 실행될 때, 마지막 REDO 체크포인트 위치부터 시작해서, 트랜잭션 로그를 이용한 redo 작업을 진행한다.
이때, 그 작업 대상이 되는 실재 데이터파일이 존재하지 않더라도, 그 redo 작업은 무시되면서, 계속 진행하고, 마지막 redo 작업을 할 것이 없다면, db서버에 사용자들이 접속 할 수 있도록 한다.
즉, db를 오픈하기 위한 최소한의 작업이 정상적으로 진행되었다면, redo 작업들이 대부분 실패를 한다고 하더라도, 데이터베이스 서버는 복구 작업 끝에 서비스를 시작하게 된다.
1. 사전 전략
데이터베이스를 복구하기 위한 베이스 백업용 데이터클러스터의 크기를 최소화 한다.
즉, global 자료와 각 데이터베이스 시스템 카탈로그 자료를 제외한 모든 자료는 $PGDATA가 아닌 전혀 다른 새로운 테이블 스페이스에 보관한다.
객체를 만들 때, 테이블 스페이스를 지정할 수 있는 객체(테이블과 인덱스)들은 모두 기본 테이블 스페이스가 아닌 사용자가 만든 새로운 테이블 스페이스에 만들어지도록 한다.
이렇게 해서, 새롭게 구축할 복구용 서버를 위한 $PGDATA 영역을 준비하는데 필요한 시간을 최소화 한다.
2. 복구방법
2.1. 새 $PGDATA 구축
recovery.conf 기반 복구를 위해서, postmaster.pid 파일도 지우고, pg_xlog 안에 있는 것도 지우고, recovery.conf 파일도 준비해둔다.
(미리 백업을 받을 때 이 작업들을 미리 준비해도 좋을 것이다.)
단순하게 복구용 데이터베이스만 만들기 때문에, 새 postgresql.conf 파일에 있는 archive_mode는 off로 지정하는 것이 좋겠다.
같은 호스트에서 구축한다면, 서버 포트도 바꾸고, 시스템 자원을 최소로 사용하도록 몇몇 환경 설정을 바꿀 필요도 있을 것이다.
이 작업은 통상 온라인백업 복구와 같다.
2.2. 복구 대상이 되는 테이블스페이스에서 필요한 파일만! 새로운 공간에 둔다.
여러 테이블 스페이스가 있는데, 그중 하나의 테이블 스페이스 전체이거나, 아니면, 그 안에 어떤 특정 파일 일 수도 있을 것이다.
여기서 골치가 아파지는데, 어느 파일을 베이스 백업에서 가져 올 것인가를 결정하는 것이다.
이것은 pg_class 테이블을 참조해서 찾아야한다.
통상 하나의 테이블은 데이터파일과 토스트 파일과 테이블에서 사용하는 인덱스 파일들로 구성된다.
데이터파일과 토스트 파일은 꼭 필요하다.
2.3. pg_tblspc 디렉토리 정리하기
pg_tablespc는 백업할 때 그대로의 운영환경 상태이기 때문에, 복구에 사용하도록 각 심볼릭 링크를 정리한다. 특정 테이블 스페이스의 특정 테이블만 복구 할 경우라면, 그 파일이 있는 것만 심볼릭으로 잡고, 나머지는 모두 지우고, 똑같은 테이블 스페이스 oid를 이름으로 하는 빈 디렉토리만 만들어주면 된다.
2.4. redo에 사용할 트랜잭션 로그 준비
통상 온라인 백업의 복구 작업과 마찬가지로, 백업받은 트랜잭션 로그와 운영중인 DB의 pg_xlog안에 있는 쪼가리 파일들 까지 redo에 필요한 모든 파일을 한곳에 두고, recovery.conf 파일에 지정한다.
2.5. 새 복구용 데이터베이스 실행
실행을 하면, 서버 로그에 꽤 많은 오류가 보이겠지만, 복구를 원하는 객체에 대해서는 정상적인 작업을 진행할 것이다.
3. 뒷마무리
새 복구용 데이터베이스에 필요한 것들을 pg_dump나, dblink를 이용해서, 운영 DB로 옮기고, 나머지 SQL 기반으로 복구를 하거나 rename방식을 선택할 수도 있을 것이다.
4. 이 작업의 한계점
객체의 filenode 가 바뀌어버렸거나, (vacuum full이 일어난 경우) 객체가 삭제되어 filenode를 알 수 없는 상태가 되어버렸다면, 이런 경우에도 복구 할 수 있도록 pg_class (각 데이터베이스로 모두) 테이블 관리를 해주지 않는다면, 복구할 대상이 어떤 것인지 몰라서 복구를 못하게 되는 경우도 발생할 것이다.
그외 아직 풀지 못한 여러 문제점들이 있을 수도 있을 것이며, 이 작업으로 인한 손실은 전적으로 작업자 책임이다.
이 글을 쓰기까지 옆에서 도와준 오늘 진급한 모 과장에게 깊이 감사의 마음을 전한다. |