사전 백업과 복구
개념

백업과 복구

gabury1

데이터를 잃을 때를 대비해 사본을 따로 떠 두는 일이 백업입니다. 잃고 나서 그 사본으로 원래 상태를 되돌리는 일이 복구입니다. 둘은 한 짝으로 붙어 다닙니다.

상세

중요한 서류를 복사해 다른 서랍에 넣어 둡니다. 원본을 잃어도 서랍의 종이로 다시 채울 수 있습니다.

백업은 어느 시점의 데이터를 원본과 분리된 자리에 떠 두는 일입니다. 복구는 그 사본을 읽어 원래 상태를 되돌리는 일입니다. 사본을 뜨는 쪽만 있으면 목적이 끝나지 않습니다. 되돌리는 절차가 실제로 동작해야 잃은 것을 되찾습니다. 되돌린 상태는 사본을 뜬 시점의 모습입니다. 그 뒤 원본에 일어난 변경은 사본에 없습니다.

시점을 떼어 고정한다는 점이 백업의 성질을 정합니다. 원본의 변경을 계속 따라가는 사본은 원본이 잘못되는 순간 같이 잘못됩니다. 지우라는 명령이 원본에 닿으면 따라가는 사본에도 닿습니다. 백업은 그 흐름에서 한 시점을 떼어 내 붙잡아 둡니다. 그래서 사고가 난 뒤에도 사고 이전이 남습니다.

되돌릴 때 정해야 하는 값이 둘입니다. 어느 시점까지 되돌릴 수 있는가, 그리고 되돌리는 데 얼마나 걸리는가입니다. 앞의 것을 RPO(Recovery Point Objective, 복구 시점 목표), 뒤의 것을 RTO(Recovery Time Objective, 복구 시간 목표)라고 부릅니다. 사본을 자주 뜨면 잃는 구간이 짧아집니다. 대신 뜨는 부담과 보관하는 자리가 늘어납니다.

배경

원본 한 벌만 두고 있으면 되돌릴 수 없는 사건이 몇 갈래로 옵니다. 디스크가 고장 나면 그 위에 있던 것이 함께 사라집니다. 사람이 지운 것은 지운 순간에는 정상 동작으로 보입니다. 시스템은 시킨 대로 했을 뿐이라 아무 오류도 남기지 않습니다. 프로그램이 잘못된 값을 써 넣으면 그 값이 멀쩡하던 데이터를 덮어씁니다.

세 경우 모두 필요한 것은 같습니다. 사고 이전 어느 시점의 상태가 원본 바깥 어딘가에 남아 있어야 합니다. 원본을 실시간으로 따라가는 사본으로는 안 됩니다. 삭제와 덮어쓰기도 함께 따라가기 때문입니다. 그래서 흐름에서 시점을 떼어 고정하고, 그것을 원본과 다른 자리에 두는 일이 필요해졌습니다.

떠 두는 쪽을 백업, 되돌리는 쪽을 복구라고 부릅니다. 둘이 한 이름으로 붙어 다니는 것은 앞의 것만으로는 목적이 끝나지 않기 때문입니다.

갈래

백업은 한 종류가 아닙니다. 무엇을 떠내나, 서버를 켜 둔 채로 뜨나, 얼마나 떠내나, 어느 시점으로 돌아갈 수 있나 — 축이 넷입니다. 같은 시스템이 네 축 위에서 각각 다른 자리를 고를 수 있습니다.

논리 백업과 물리 백업

무엇을 떠내는가가 축입니다. 물리 백업은 데이터베이스 내용을 저장하는 디렉터리와 파일을 있는 그대로 복사한 것입니다. 논리 백업은 논리적인 데이터베이스 구조와 내용으로 표현된 정보를 저장하는 것입니다. 구조는 CREATE DATABASE · CREATE TABLE 문으로, 내용은 INSERT 문이나 구분자로 나뉜 텍스트 파일로 적힙니다. 물리 백업 방식은 변환 없이 파일 복사만 하므로 논리 방식보다 처리가 빠릅니다. 대신 물리 백업은 서버가 도는 중이라면 백업하는 동안 서버가 내용을 바꾸지 않도록 적절한 잠금을 걸어야 합니다. 논리 백업은 서버를 켜 둔 채로 수행합니다.

같은 두 자리를 SQL(Structured Query Language, 구조화 질의 언어) 덤프와 파일 시스템 수준 백업으로 부르는 쪽도 있습니다. SQL 덤프는 서버에 다시 먹이면 덤프 시점과 같은 상태로 데이터베이스를 재생성하는 SQL 명령 파일을 만드는 방식입니다. 이 방식의 이점은 덤프 출력을 대체로 상위 판 서버에도 다시 적재할 수 있다는 점입니다. 파일 수준 백업과 연속 아카이빙은 둘 다 서버 판에 극도로 의존적입니다. 파일 수준 백업에는 제약이 둘 붙습니다. 쓸 만한 백업을 얻으려면 데이터베이스 서버를 내려야 하고, 전체 데이터베이스 클러스터 단위로만 백업과 복원이 됩니다. 파일 시스템이 일관된 스냅샷을 지원하면 서버를 켜 둔 채로도 됩니다. 볼륨을 얼린 스냅샷을 뜨고, 그 스냅샷에서 데이터 디렉터리 전체를 백업 장치로 복사한 다음, 얼린 스냅샷을 놓아 주는 것이 일반적인 절차입니다.

온라인 백업과 오프라인 백업

서버가 도는 중에 뜨는가가 축입니다. 온라인 백업은 서버가 도는 동안 이뤄지는 백업입니다. 서버가 돌고 있으므로 데이터베이스 정보를 서버에서 얻어올 수 있습니다. 오프라인 백업은 서버가 멈춘 동안 이뤄집니다. 이 구분을 핫 백업과 콜드 백업으로도 부릅니다. 웜 백업은 그 사이입니다. 서버는 계속 돌지만 데이터를 바꾸지 못하도록 잠긴 상태에서 데이터베이스 파일을 바깥에서 건드립니다.

이 축은 무엇을 떠내는가와 따로 섭니다. 물리 백업은 서버가 멈춘 동안 뜰 수 있고, 도는 중이라면 적절한 잠금을 걸어 뜹니다. 일관된 스냅샷을 뜨는 파일 시스템 수준 백업은 서버가 도는 채로도 동작합니다.

전체 백업과 증분 백업

얼마나 떠내는가가 축입니다. 전체 백업은 주어진 시점에 서버가 관리하는 모든 데이터이고, 증분 백업은 주어진 기간 동안 데이터에 가해진 변경입니다. 증분 백업은 서버의 바이너리 로그를 켜야 가능해집니다. 데이터 변경을 기록하는 것이 그 로그이기 때문입니다.

관리형 서비스와 파일 복사 도구에도 같은 축이 있습니다. 첫 스냅샷에 전체 데이터를 담고 그 뒤 스냅샷은 가장 최근 스냅샷 이후 바뀐 데이터만 담는 식입니다. 파일 단위에서는 바뀌지 않은 파일을 다시 복사하지 않고 이미 있는 사본에 하드링크로 걸어 같은 축을 만듭니다.

고정 시점과 시점 복구

어느 시점으로 돌아갈 수 있는가가 축입니다. 덤프나 스냅샷 하나는 그것을 뜬 시점 하나로만 돌아갑니다. 그 사이 아무 시각으로나 돌아가려면 시점과 시점 사이의 변경 기록이 함께 있어야 합니다. 그 기록을 WAL(Write-Ahead Log, 미리 쓰기 로그)이라고 부릅니다. 데이터 파일에 가해진 모든 변경이 여기 적힙니다. 앞의 두 방식에 더해, 파일 시스템 수준 백업과 이 WAL 파일 백업을 합친 세 번째 방식이 있습니다. 복구가 필요하면 파일 시스템 백업을 되돌린 다음 백업해 둔 WAL 파일을 재생해 현재 상태까지 끌어올립니다.

WAL 항목을 끝까지 재생할 필요는 없습니다. 아무 지점에서 재생을 멈추면 그 시각의 일관된 데이터베이스 스냅샷을 얻습니다. 그래서 이 방식은 시점 복구를 지원합니다. 베이스 백업을 뜬 이후의 아무 시각으로나 데이터베이스를 되돌릴 수 있습니다. 같은 것을 증분 복구라고 부르는 쪽도 있습니다. 서버 상태를 주어진 시각까지 현재화하기 때문에 시점 복구라는 이름이 같이 붙습니다.

flowchart TD
    A[베이스 백업] --> B[되돌린다]
    B --> C[아카이브된 로그 재생]
    C --> D{목표 시각인가}
    D -- 아니다 --> C
    D -- 맞다 --> E[그 시각의 상태]

베이스 백업을 먼저 되돌리고, 아카이브해 둔 로그를 앞에서부터 재생합니다. 목표로 정한 시각에 닿으면 재생을 멈춥니다. 그 자리가 복구된 상태입니다.

예시

pg_dump 와 pg_restore

PostgreSQL 은 SQL 덤프를 위해 pg_dump 유틸리티 프로그램을 제공합니다. 기본 사용법은 이렇습니다.

pg_dump dbname > dumpfile

pg_dump 는 결과를 표준 출력으로 씁니다. 텍스트 덤프는 psql 프로그램이 기본 설정으로 읽도록 만들어져 있습니다. 되돌리는 명령 형태는 이렇습니다.

psql -X dbname < dumpfile

이때 데이터베이스는 psql 이 만들어 주지 않으므로 template0 에서 먼저 만들어 둬야 합니다. 텍스트가 아닌 덤프는 pg_restore 로 되돌립니다.

pg_restore -d dbname filename

custom 덤프 포맷은 psql 용 스크립트가 아니라서 이 경로를 거쳐야 합니다. PostgreSQL 이 zlib 압축 라이브러리가 깔린 시스템에서 빌드됐으면 이 포맷은 출력 파일에 쓰면서 데이터를 압축합니다. 그리고 테이블을 골라서 복원할 수 있습니다.

archive_command 와 recovery_target_time

연속 아카이빙을 켜면 WAL 세그먼트를 어디로 옮길지 서버 설정에 적어 둡니다.

archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'

이 값은 아카이브 대상 WAL 세그먼트를 /mnt/server/archivedir 디렉터리로 복사합니다. 되돌릴 때는 반대 방향을 적습니다. restore_command 가 아카이브해 둔 WAL 파일 세그먼트를 어떻게 가져올지 PostgreSQL 에 알려 줍니다.

restore_command = 'cp /mnt/server/archivedir/%f %p'

어느 시각까지 재생할지는 recovery_target_time 이 정합니다. PostgreSQL 서버 설정 문서는 이 파라미터가 복구가 진행할 타임스탬프를 지정한다고 적습니다. 정확한 정지 지점은 recovery_target_inclusive 의 영향도 받습니다. recovery_target · recovery_target_lsn · recovery_target_name · recovery_target_time · recovery_target_xid 중 하나만 쓸 수 있고, 설정 파일에 둘 이상을 적으면 오류가 납니다. 이 파라미터들은 서버 시작 시점에만 설정됩니다.

mysqldump

MySQL 의 논리 백업 도구는 mysqldump 입니다. 호출 형태가 셋입니다.

mysqldump [options] db_name [tbl_name ...]
mysqldump [options] --databases db_name ...
mysqldump [options] --all-databases

덤프 파일을 다시 적재할 때는 mysql 클라이언트로 흘려 넣습니다.

mysql [options] db_name < dump.sql

rsync --link-dest

파일 단위 백업에서는 rsync 가 같은 자리를 맡습니다. rsync 매뉴얼은 커다란 문서 파일과 메일 폴더로 이루어진 홈 디렉터리를 백업하는 사용자별 cron 작업의 예로 이 줄을 듭니다.

rsync -aiz . bkhost:backup/joe/

증분을 만들 때는 --link-dest 를 붙입니다.

rsync -av --link-dest=$PWD/prior_dir host:src_dir/ new_dir/

--link-dest 는 바뀌지 않은 파일을 지정한 디렉터리에서 목적지 디렉터리로 하드링크합니다. 파일이 하드링크로 묶이려면 권한이나 소유권처럼 보존되는 속성이 전부 같아야 합니다. rsync 매뉴얼은 이 옵션이 비어 있는 목적지 계층으로 복사할 때 가장 잘 동작한다고 적습니다. 백업을 모아 둘 자리를 따로 지정하는 --backup-dir 도 있습니다. 매뉴얼은 이 옵션이 증분 백업에 쓰일 수 있다고 적습니다.

관련 항목

이것의 하위 갈래

물리 백업 · 논리 백업 · 전체 백업 · 증분 백업 · 콜드 백업 · 핫 백업 · 웜 백업 · 시점 복구

사본을 뜨는 방식

스냅샷 · 베이스 백업 · 덤프 · WAL 아카이빙 · 하드링크

복구에서 정하는 기준과 순서

복구 시점 목표 · 복구 시간 목표 · 보존 기간 · 복구 목표 시각 · 복원 순서

복구가 딛고 서는 로그 메커니즘

로그 · WAL · 체크포인트 · 바이너리 로그

이것이 다루는 저장 대상

데이터베이스 · 클러스터 · 테이블 · 세그먼트

가용성을 지키는 다른 전략

복제 · 웜 스탠바이 · 고가용성 · 재해 복구

백업을 다루는 운영 관행

무결성 검증 · 복구 훈련 · 오프사이트 보관

이것을 구현하는 도구와 서비스

PostgreSQL · MySQL · pg_dump · pg_restore · pg_basebackup · mysqldump · rsync · Amazon RDS · Amazon RDS 자동 백업 · LVM 스냅샷 · ZFS 스냅샷 · Restic · Velero

예시에 등장하는 주변 기술

SQL · zlib · cron · 타임스탬프 · 권한

다른 이름: backup and recovery · backup · restore · 백업 · 복구 · backup and restore