MariaDB / DATABASE / 백업하기, 복원하기

MariaDB는 mariadb-dump로 구조와 데이터를 SQL 파일에 백업하고, mariadb 클라이언트로 그 SQL을 실행해 복원할 수 있습니다. 한 데이터베이스는 데이터베이스명, 여러 개는 --databases, 서버 범위는 --all-databases로 지정합니다. 백업 파일 생성만으로 완료하지 말고, 원본과 분리된 대상에 복원해 데이터와 필요한 객체를 확인해야 합니다.

실행 전 대상·도구·백업 범위 확인

아래 명령은 MariaDB 클라이언트 도구가 설치되어 PATH에서 실행되는 환경을 전제로 합니다. SQL은 MariaDB 접속에서, bash 명령은 Linux·macOS의 Bash 셸에서 실행합니다. 예제 접속은 로컬 TCP 127.0.0.1:3306이며 사용자명·포트·경로를 실제 환경에 맞게 바꿉니다. 원격 접속은 제공자의 TLS·인증서 검증 설정까지 별도로 적용하세요. -p 또는 --password 뒤에 비밀번호를 적지 않으면 입력을 요청합니다.

mariadb-dump --version
mariadb --version

백업 계정에는 테이블 SELECT와 대상 객체에 맞는 SHOW VIEW·TRIGGER·EVENT·루틴 조회 권한 등이 필요합니다. 복원 계정에는 파일 속 CREATE·INSERT·DROP·루틴 등의 실행 권한이 필요합니다. 부족한 권한은 필요한 범위로 관리자와 조정하며 백업 실패를 --force로 무시하지 않습니다. DEFINER가 있는 뷰·루틴·트리거는 복원 대상의 계정과 실행 권한도 확인합니다.

논리 백업과 물리 백업의 차이에서 설명하듯 SQL 덤프는 서버 설정 파일·로그·애플리케이션 파일을 함께 보관하는 방식이 아닙니다. 큰 데이터의 복원 시간이나 시점 복구 요구가 있으면 물리 백업·바이너리 로그 보관도 별도로 설계합니다. 복제본 하나만으로 삭제·오류까지 되돌릴 백업을 대신하지 않습니다.

한 데이터베이스를 SQL 파일로 백업

app_db가 원본이라고 가정합니다. 백업 디렉터리를 만들고 파일명을 매번 다르게 지정합니다. SQL 덤프에는 원본 데이터가 들어 있으므로 웹 공개 폴더에 두지 말고 파일 접근 권한과 별도 보관소의 암호화·보존 정책을 적용합니다. 다음 명령은 Bash에서 실행하며, 파일명 확인과 성공 검사를 포함합니다.

umask 077
mkdir -p ./backups
backup_file="./backups/app-db-$(date +%Y%m%d-%H%M%S).sql"
if [ -e "$backup_file" ]; then
    echo "Choose a new backup filename." >&2
elif mariadb-dump --host=127.0.0.1 --port=3306 --user=backup_user --password \
    --default-character-set=utf8mb4 --single-transaction --quick \
    --routines --events --triggers --hex-blob \
    --result-file="$backup_file" app_db; then
    test -s "$backup_file" && echo "Dump created; restore validation is required."
else
    echo "Dump failed. Do not treat the partial file as a valid backup." >&2
fi

--single-transaction은 InnoDB 데이터의 일관된 읽기를 위한 옵션입니다. 백업 중 ALTER·DROP·TRUNCATE 같은 구조 변경을 진행하지 않고, MyISAM·MEMORY 등에는 같은 일관성 보장을 기대하지 않습니다. --quick은 행을 순차적으로 읽도록 하며 --routines·--events는 저장 루틴과 이벤트를 포함합니다. --triggers는 기본 포함되는 트리거의 의도를 명시하고 --hex-blob은 바이너리 데이터를 16진수로 출력합니다.

--result-file은 셸의 출력 리디렉션 대신 도구가 직접 파일을 쓰게 합니다. mariadb-dump 옵션 문서에 따라 기존 파일을 덮어쓸 수 있고 실패해도 불완전한 파일이 생길 수 있으므로, 새 이름과 종료 상태를 모두 확인합니다. 파일 크기나 끝의 완료 문구만으로 복구 가능성을 확정하지 않습니다.

여러 데이터베이스와 서버 범위 백업

여러 데이터베이스를 한 파일에 담으려면 --databases가 필요합니다. 이 옵션 없이 app_db analytics_db라고 쓰면 둘째 이름을 app_db 안의 테이블명으로 해석합니다. 아래 파일도 새 이름인지 먼저 확인한 뒤 실행합니다.

mariadb-dump --host=127.0.0.1 --port=3306 --user=backup_user --password \
    --single-transaction --quick --routines --events --triggers --hex-blob \
    --result-file=./backups/two-databases-new.sql \
    --databases app_db analytics_db

--databases 덤프에는 CREATE DATABASE와 USE 문장이 포함됩니다. 따라서 복원 접속에서 다른 기본 데이터베이스를 지정해도 파일 안의 USE가 대상을 바꿀 수 있습니다. 이름만 바꾸어 임의의 데이터베이스로 복원할 수 있다고 생각하지 마세요. 다른 이름으로 시험 복원하려면 앞 절처럼 --databases 없이 단일 데이터베이스를 덤프한 파일을 먼저 검토합니다. 객체 정의 안에 원본 데이터베이스를 명시한 참조가 있을 수도 있습니다. 이런 객체는 원본과 격리한 별도 서버에서 원래 이름을 유지해 복원하거나, 참조를 검토하고 의도한 대상으로 다시 정의한 뒤 검증합니다.

mariadb-dump --host=127.0.0.1 --port=3306 --user=backup_user --password \
    --single-transaction --quick --routines --events --triggers --hex-blob \
    --result-file=./backups/all-databases-new.sql --all-databases

--all-databases는 시스템 데이터베이스까지 포함할 수 있는 넓은 범위입니다. INFORMATION_SCHEMA·PERFORMANCE_SCHEMA는 기본 덤프 대상과 다르며, 이 명령 하나가 서버 설정과 로그까지 완전히 복제하는 것은 아닙니다. 시스템 테이블의 스토리지 엔진과 버전 차이 때문에 --single-transaction만으로 서버 전체의 일관성을 보장할 수도 없습니다. 전체 덤프를 다른 버전에 무조건 덮어쓰기보다 해당 버전의 복원·업그레이드 절차와 필요한 계정·권한 백업을 확인합니다.

원본과 분리된 데이터베이스에 복원

단일 데이터베이스 덤프를 app_db_restore라는 새 시험용 데이터베이스에 복원하는 예입니다. 기존 동명 데이터베이스가 있으면 새 이름을 선택하며 IF NOT EXISTS로 넘어가지 않습니다. 복원 전 @@hostname·@@port·DATABASE()로 접속 대상도 다시 확인하세요. 실제 업무에서는 운영 원본과 격리된 복원 서버를 권장하며 아래는 별도 데이터베이스를 사용하는 기본 절차입니다.

CREATE DATABASE app_db_restore CHARACTER SET utf8mb4;
SELECT @@hostname AS server_host, @@port AS server_port, DATABASE() AS current_database;

Bash에서 백업 파일의 실제 경로로 바꾸어 실행합니다. 기존 객체를 DROP하거나 같은 이름으로 만들 수 있는 SQL이 들어 있으므로 빈 시험 대상인지, 파일 안에 USE·데이터베이스 한정 이름·원치 않는 관리 문장이 없는지 먼저 확인합니다. 출처를 모르는 SQL 파일은 그대로 실행하지 않습니다.

if mariadb --host=127.0.0.1 --port=3306 --user=restore_user --password \
    --default-character-set=utf8mb4 --abort-source-on-error \
    app_db_restore < ./backups/app-db-selected.sql; then
    echo "Import finished; compare data and objects."
else
    echo "Import failed. The target may be only partially restored." >&2
fi

가져오기는 파일 안의 DDL과 데이터 변경을 순서대로 실행합니다. 전체 파일이 하나의 원자적 트랜잭션처럼 되돌려지는 것은 아니므로 오류 뒤의 부분 복원을 정상 상태로 쓰지 않습니다. 원인을 해결한 뒤 새 빈 시험 대상에서 다시 복원하고, 검증 전에는 애플리케이션 연결을 바꾸지 않습니다. 원본에 직접 덮어쓴 뒤 ROLLBACK으로 전체 복원을 취소할 수 있다고 기대해서도 안 됩니다.

여러 데이터베이스·전체 덤프는 파일 속 데이터베이스 이름을 사용하므로 아래처럼 기본 데이터베이스명 없이 가져옵니다. 예제의 3307은 별도로 준비한 빈 격리 시험 서버를 뜻합니다. 기존 운영 서버에 해당 주소를 그대로 대입하지 않습니다.

mariadb --host=127.0.0.1 --port=3307 --user=restore_user --password --abort-source-on-error < ./backups/two-databases-new.sql

Windows PowerShell에서 백업·복원

PowerShell에서는 Bash의 < 입력 리디렉션 예제를 그대로 사용할 수 없습니다. 실제 설치된 bin 경로로 아래 실행 파일 경로를 바꾸고, 존재하는 접근 제한 백업 폴더의 새 파일을 사용합니다. 백업에는 --result-file을 사용하고 종료 코드는 바로 검사합니다.

& 'C:/MariaDB/bin/mariadb-dump.exe' --host=127.0.0.1 --port=3306 --user=backup_user --password --single-transaction --quick --routines --events --triggers --hex-blob --result-file=C:/db-backups/app-db-new.sql app_db
if ($LASTEXITCODE -ne 0) { throw 'Backup failed; inspect the partial file.' }

복원은 mariadb 클라이언트를 실행한 뒤 해당 클라이언트 프롬프트에서 SOURCE 명령으로 파일을 읽을 수 있습니다. 파일 경로는 공백이 없는 예시로 제시합니다. SOURCE는 서버 SQL문이 아니라 클라이언트 명령이며 파일은 클라이언트가 실행되는 컴퓨터에 있어야 합니다.

& 'C:/MariaDB/bin/mariadb.exe' --host=127.0.0.1 --port=3306 --user=restore_user --password --default-character-set=utf8mb4 --abort-source-on-error app_db_restore
SOURCE C:/db-backups/app-db-new.sql;

새 mariadb-dump가 생성한 파일 첫 부분에는 클라이언트 샌드박스 명령이 들어갈 수 있습니다. 이를 이해하지 못하는 오래된 mariadb나 mysql 클라이언트에서 오류가 나면 파일의 안전장치를 임의로 지우기보다 호환되는 MariaDB 클라이언트를 사용합니다. 클라이언트의 SOURCE·샌드박스 동작과 덤프 생성 버전을 함께 확인하세요.

행·한글·뷰·루틴·이벤트 검증

원본과 복원 대상에서 같은 시점의 기준 자료를 비교합니다. 행 수만 같아도 값은 다를 수 있으므로 주요 키·금액·날짜·NULL·한글·바이너리 값의 표본이나 정렬된 전체 비교를 추가합니다. 운영 원본이 계속 바뀌는 경우 현재 값이 아니라 백업 시점의 검증 기준을 남겨야 합니다.

SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'app_db_restore' ORDER BY TABLE_NAME;
SELECT ROUTINE_NAME, ROUTINE_TYPE FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA = 'app_db_restore' ORDER BY ROUTINE_NAME;
SELECT TRIGGER_NAME FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA = 'app_db_restore' ORDER BY TRIGGER_NAME;
SELECT EVENT_NAME, STATUS FROM information_schema.EVENTS
WHERE EVENT_SCHEMA = 'app_db_restore' ORDER BY EVENT_NAME;

조회에 필요한 메타데이터 권한이 있어야 하며, 목록이 보인다는 사실만으로 객체 실행 권한까지 정상이라고 확정하지 않습니다. 업무 테이블은 정확한 COUNT(*)와 중요한 합계·범위·문자열 표본을 비교하고 뷰 조회·루틴 호출도 시험합니다. 이벤트는 복원 환경에서 의도치 않게 작업을 실행하지 않도록 상태와 스케줄러 설정을 먼저 확인합니다. DEFINER 계정 누락이나 원본 데이터베이스를 가리키는 참조가 있으면 운영 전환 전에 해결합니다.

백업 명령의 종료 상태, 파일 크기·해시·보관 위치, 생성 도구·서버 버전, 실제 복원과 검증 결과를 함께 기록합니다. 해시는 파일이 전송 중 바뀌었는지를 비교하는 자료이며 복원 성공을 대신하지 않습니다. 정기적인 복원 시험에서 걸리는 시간과 복구 범위를 확인하고, 원본을 바꾸지 않은 상태에서 시험 대상만 정리할 수 있도록 대상을 분명히 구별합니다.