AD JB Toolbox 01

MariaDB 강좌 / 백업을 별도 데이터베이스에 복원하고 검증하기

백업 검증은 원본과 다른 빈 데이터베이스에 복원하고 구조·행·제약 조건·업무 합계를 대조하는 과정입니다. 덤프 안의 DB 전환·삭제 문장을 확인하고 오류에서 멈춘 뒤 원인을 해결해야 원본이나 다른 데이터를 잘못 덮어쓰는 일을 줄일 수 있습니다.

다른 DB 이름만 지정하면 안전하다고 가정하지 않기

덤프에 CREATE DATABASE·USE·완전 수식된 객체명이 들어 있으면 연결할 때 지정한 대상 DB와 다른 곳으로 작업할 수 있습니다. 복원 전에 파일을 검토하고 출처·버전·옵션을 확인하세요. 기본 덤프에는 DROP TABLE 같은 문장이 들어 있을 수 있으므로 기존 데이터가 있는 DB에 시험하지 않습니다. 원본 파일 생성 조건은 mariadb-dump로 데이터베이스 백업하기, 주문 변경까지 포함한 종합 복원 기준은 최종 실습: 주문 데이터베이스 구축부터 권한·백업·복원까지과 대조할 수 있습니다.

검증 단계 확인 대상 판단 기준
파일 검토 CREATE DATABASE·USE·DROP·DEFINER 대상 밖 작업 여부
빈 대상 준비 실제 서버·DB 이름·권한 원본과 분리
복원 실행 첫 오류·종료 코드 부분 성공과 전체 성공 구분
검증 객체·행·키·업무 값 원본 기준과 일치

독립 실행용 원본과 덤프 준비하기

이 글은 restore47_source와 restore47_target이라는 새 이름을 사용합니다. 기존 이름이 없는지 관리자가 확인하고 아래 전체 데이터를 준비합니다. 앞 글의 백업을 사용하는 경우에는 그 파일 안의 테이블명·원본 기준값으로 검증 쿼리를 바꿔야 합니다. 두 실습 파일을 섞지 않습니다.

CREATE DATABASE restore47_source CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE restore47_source;
CREATE TABLE c47_customers (
 customer_id INT NOT NULL PRIMARY KEY,
 customer_name VARCHAR(50) NOT NULL,
 city VARCHAR(30) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE c47_products (
 product_id INT NOT NULL PRIMARY KEY,
 product_name VARCHAR(100) NOT NULL,
 category VARCHAR(30) NOT NULL,
 price DECIMAL(10,2) NOT NULL CHECK (price >= 0),
 stock INT NOT NULL CHECK (stock >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE c47_orders (
 order_id INT NOT NULL PRIMARY KEY,
 customer_id INT NOT NULL,
 ordered_at DATETIME NOT NULL,
 status VARCHAR(20) NOT NULL,
 shipping_fee DECIMAL(10,2) NOT NULL DEFAULT 1000,
 CONSTRAINT fk_c47_order_customer FOREIGN KEY (customer_id)
  REFERENCES c47_customers(customer_id) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE c47_items (
 order_id INT NOT NULL,
 product_id INT NOT NULL,
 quantity INT NOT NULL CHECK (quantity > 0),
 unit_price DECIMAL(10,2) NOT NULL CHECK (unit_price >= 0),
 PRIMARY KEY (order_id, product_id),
 CONSTRAINT fk_c47_item_order FOREIGN KEY (order_id)
  REFERENCES c47_orders(order_id) ON DELETE RESTRICT,
 CONSTRAINT fk_c47_item_product FOREIGN KEY (product_id)
  REFERENCES c47_products(product_id) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO c47_customers VALUES
 (1,'김민수','서울'),(2,'이서연','부산'),
 (3,'박지우','서울'),(4,'최하늘','대전');
INSERT INTO c47_products VALUES
 (1,'노트','문구',3500,20),(2,'볼펜','문구',1500,50),
 (3,'머그컵','생활',8000,12),(4,'스탠드','생활',25000,5);
INSERT INTO c47_orders
 (order_id,customer_id,ordered_at,status,shipping_fee) VALUES
 (101,1,'2026-01-10 10:00:00','paid',1000),
 (102,1,'2026-01-20 11:00:00','paid',1000),
 (103,2,'2026-02-05 12:00:00','paid',1000),
 (104,3,'2026-02-10 13:00:00','canceled',1000);
INSERT INTO c47_items VALUES
 (101,1,2,3500),(101,2,3,1500),(102,3,1,8000),
 (103,1,1,3500),(103,3,2,8000),(104,2,1,1500);

course_user에 해당 실습 DB들의 권한을 별도로 부여한 뒤 새 파일로 덤프합니다. 이 권한은 실제 운영 DB의 일괄 권한 부여를 뜻하지 않습니다.

GRANT ALL PRIVILEGES ON restore47_source.* TO 'course_user'@'127.0.0.1';
CREATE DATABASE restore47_target CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON restore47_target.* TO 'course_user'@'127.0.0.1';
New-Item -ItemType Directory -Path 'C:/mariadb-lab' -Force | Out-Null
$courseBackupPath='C:/mariadb-lab/restore47-source.sql'
if (Test-Path -LiteralPath $courseBackupPath) { throw 'Choose a new backup filename.' }
mariadb-dump --protocol=tcp --host=127.0.0.1 --port=3306 --user=course_user --password --default-character-set=utf8mb4 --single-transaction --quick --skip-lock-tables --result-file=$courseBackupPath restore47_source
if ($LASTEXITCODE -ne 0) { throw 'Backup failed; do not restore this file.' }
Get-Item -LiteralPath $courseBackupPath | Select-Object Name,Length
Get-FileHash -LiteralPath $courseBackupPath -Algorithm SHA256

Ubuntu 셸에서 실행하는 대안입니다. Windows PowerShell 코드와 둘 중 하나만 사용합니다. 괄호 안의 umask와 덮어쓰기 방지 설정은 현재 터미널 전체에 남지 않습니다.

mkdir -p "$HOME/mariadb-lab"
(
  umask 077
  set -C
  backup_file="$HOME/mariadb-lab/restore47-source.sql"
  if mariadb-dump --protocol=tcp --host=127.0.0.1 --port=3306 \
      --user=course_user --password --default-character-set=utf8mb4 \
      --single-transaction --quick --skip-lock-tables restore47_source > "$backup_file"; then
    test -s "$backup_file" || exit 1
    sha256sum "$backup_file"
  else
    printf '%s\n' 'Backup failed; preserve the partial file for diagnosis.' >&2
    exit 1
  fi
)

이미 같은 이름이 있으면 덮어쓰지 않고 실패합니다. 명령이 실패한 경우 남은 파일은 정상 백업으로 사용하지 말고 새 파일명으로 다시 검증합니다. 크기·SHA-256은 보관 증거이며 복원 성공을 대신하지 않습니다.

접속에서 TLS 오류가 나면 서버·클라이언트 버전과 인증서 이름, 신뢰할 CA, 필요한 클라이언트 인증서를 공식 TLS 연결 조건에 맞춰 확인합니다. 서버에 맞는 옵션 파일이나 인증서 옵션을 백업·복원 클라이언트에도 적용하며, 오류를 피하려고 인증서 검증을 기본적으로 끄지 않습니다.

빈 대상을 다시 확인하고 같은 버전 도구로 복원하기

터미널에서 대상 DB로 연결하고 VERSION·DATABASE를 확인합니다. SHOW TABLES가 비어 있는지 확인한 다음 SOURCE로 파일을 읽습니다. SQL 파일은 내용이 신뢰되는지 먼저 검토하고 실행하며, 다른 사용자 파일을 검토 없이 가져오지 않습니다.

mariadb --abort-source-on-error --protocol=tcp --host=127.0.0.1 --port=3306 --user=course_user --password --default-character-set=utf8mb4 restore47_target
SELECT VERSION(),DATABASE();
SHOW TABLES;
SOURCE C:/mariadb-lab/restore47-source.sql;

최근 mariadb-dump는 파일 앞에 sandbox 관련 지시문을 넣을 수 있어 이를 지원하지 않는 구형 MariaDB·MySQL 클라이언트에서 오류가 날 수 있습니다. 지시문을 무조건 삭제하는 대신 호환되는 MariaDB 도구 조합을 확인합니다. 덤프 파일과 클라이언트 호환성 안내를 참고하세요.

Ubuntu에서 복원할 때는 다음 명령으로 같은 대상에 접속합니다. 이어지는 SOURCE는 실제 로그인 이름과 앞에서 만든 파일의 절대 경로로 바꾸세요.

mariadb --abort-source-on-error --protocol=tcp --host=127.0.0.1 --port=3306 --user=course_user --password --default-character-set=utf8mb4 restore47_target
SELECT DATABASE();
SHOW TABLES;
SOURCE /home/learner/mariadb-lab/restore47-source.sql;

Windows와 Ubuntu의 복원 예제를 같은 대상에서 둘 다 실행하지 않습니다. 오류 중단 옵션은 SOURCE의 후속 문장 실행을 멈추지만 앞서 생성된 테이블이나 확정된 변경을 자동 취소하지 않습니다. 실패하면 원인을 해결하고 새로운 빈 대상에서 다시 검증합니다.

테이블 수·행 수·관계·업무 금액 비교하기

SELECT TABLE_NAME,TABLE_TYPE FROM information_schema.TABLES
WHERE TABLE_SCHEMA='restore47_target' ORDER BY TABLE_NAME;
SELECT (SELECT COUNT(*) FROM restore47_target.c47_customers) AS customers,
 (SELECT COUNT(*) FROM restore47_target.c47_products) AS products,
 (SELECT COUNT(*) FROM restore47_target.c47_orders) AS orders_count,
 (SELECT COUNT(*) FROM restore47_target.c47_items) AS detail_rows;
SELECT SUM(i.quantity*i.unit_price) AS paid_goods
FROM restore47_target.c47_orders o
JOIN restore47_target.c47_items i ON i.order_id=o.order_id WHERE o.status='paid';
SHOW CREATE TABLE restore47_target.c47_items;

기본 테이블 네 개, 고객 4·상품 4·주문 4·상세 6, paid 상품 금액 39000.00이 예상됩니다. SHOW CREATE TABLE에서 기본키·외래키·수량·단가의 제약도 확인합니다. 행 수가 같아도 행 내용이 다를 수 있으므로 기본키별 원본 값과 핵심 집계, 필요한 업무 조회를 함께 비교해야 합니다.

뷰·루틴·트리거·이벤트가 있는 실제 시스템은 객체 수와 실행 동작도 검증합니다. 덤프가 계정·권한·서버 설정까지 자동 복구한다고 가정하지 않고 필요한 정의자·호출 계정의 권한을 따로 확인합니다.

오류에서 멈추고 부분 복원 상태를 구분하기

문법·권한·정의자·문자 집합 오류가 발생하면 이미 일부 객체가 생성되었을 수 있습니다. --force로 계속 진행한 결과를 정상 복원으로 보고하지 않습니다. 오류와 생성된 객체를 기록하고 원인을 해결한 뒤 새로운 빈 대상에서 다시 검증하는 편이 명확합니다.

외래키 오류를 없애려고 임의로 검사 설정만 끄지 않습니다. 파일이 원래 넣고 복원하는 설정을 확인하고 종료 시 연결 상태도 확인합니다. DDL·복원 전체가 하나의 ROLLBACK으로 취소될 것이라고 생각하면 안 됩니다. 운영 복구의 전환·접속 차단·후속 쓰기 방지는 별도 승인된 절차가 필요합니다.

검증 증거와 보관 필요성을 확인하기

원본 덤프의 해시·도구 버전·대상 서버·복원 시간·검증 쿼리와 결과를 기록합니다. 모든 검증이 끝나기 전에 원본 DB나 백업을 지우지 않습니다. 실습 후 DB를 정리하려면 각 이름이 이 글에서 만든 폐기 가능한 대상인지 다시 확인하고 필요한 자료를 별도로 보관한 뒤 관리자 권한으로 처리합니다. 이 글은 자동 DROP DATABASE를 실행하지 않습니다.

같은 카테고리의 다른 글
MariaDB / 피벗 테이블 만드는 방법

MariaDB / 피벗 테이블 만드는 방법

피벗 테이블은 엑셀의 유용한 기능 중의 하나입니다. 예를 들어 아래의 왼쪽 데이터를 오른쪽 표처럼 만드는 것이 피벗 테이블입니다. 조건에 따라 그룹화시켜서 보기 좋게 데이터를 정리하는 것이라 보면 됩니다. MariaDB에서도 몇 가지 함수를 이용하여 피벗 테이블을 만들 수 있습니다.

MariaDB 강좌 / 문자열 다루기: 연결·추출·치환·길이

MariaDB 강좌 / 문자열 다루기: 연결·추출·치환·길이

문자열 연결·추출·치환과 길이 계산을 상품 데이터로 실습합니다. NULL과 빈 문자열의 연결 차이, UTF-8 문자 수·바이트 수, 원본을 보존하며 가공 결과를 확인하는 기준을 설명합니다.

MariaDB 강좌 / 기본키·AUTO_INCREMENT·UNIQUE로 행 식별하기

MariaDB 강좌 / 기본키·AUTO_INCREMENT·UNIQUE로 행 식별하기

기본키·자동 증가·고유 제약을 고객 데이터로 구분하고 중복 입력을 확인합니다. nullable UNIQUE, 복합 기본키와 트랜잭션 취소 후 자동 번호가 빠지는 경우를 실습합니다.

MariaDB 강좌 / 여러 테이블 JOIN하기: 중복 행과 집계 오류 확인

MariaDB 강좌 / 여러 테이블 JOIN하기: 중복 행과 집계 오류 확인

고객·주문·상세·상품을 JOIN하고 행 증가에 따른 배송비 중복 합산을 확인합니다. COUNT DISTINCT와 SUM DISTINCT의 차이, 주문별 선집계로 올바른 금액을 얻는 방법을 설명합니다.

MariaDB / 데이터베이스 / 조회, 생성, 삭제, 이름 변경

MariaDB / 데이터베이스 / 조회, 생성, 삭제, 이름 변경

MariaDB에서 데이터베이스를 조회하는 방법, 생성하는 방법, 삭제하는 방법, 이름을 변경하는 방법에 대해서 알아봅니다.

MariaDB 강좌 / LEFT JOIN으로 연결되지 않은 행도 조회하기

MariaDB 강좌 / LEFT JOIN으로 연결되지 않은 행도 조회하기

LEFT JOIN으로 주문 없는 고객을 유지하고 paid 주문 수를 0까지 표시합니다. ON·WHERE의 필터 위치, COUNT(*)의 함정, NULL 기본키로 미일치 행을 찾는 기준을 실습합니다.

MariaDB 강좌 / 로컬·원격 접속과 연결 오류 해결하기

MariaDB 강좌 / 로컬·원격 접속과 연결 오류 해결하기

로컬 TCP 연결을 명시하고 서버 정보·현재 계정·실제 테이블 권한을 확인합니다. 연결 거절·인증·DB 오류를 나누어 진단하고 원격 수신 주소·계정·TLS의 적용 조건을 설명합니다.

MariaDB 강좌 / Docker로 MariaDB 실습 환경 만들기

MariaDB 강좌 / Docker로 MariaDB 실습 환경 만들기

Compose 파일로 MariaDB 포트·암호 파일·데이터 볼륨·헬스체크를 구성합니다. 연결 확인과 컨테이너 교체 실습을 통해 데이터 유지, 초기화와 접속 오류의 차이를 이해합니다.

MariaDB 강좌 / INSERT로 한 행과 여러 행 추가하기

MariaDB 강좌 / INSERT로 한 행과 여러 행 추가하기

INSERT의 열·값 대응, 한 행과 다중 행 입력, 자동 번호와 기본값을 상품 데이터로 실습합니다. 저장 결과와 오류 뒤 행 수를 확인하고 기존 데이터와 분리해 반복하는 방법을 설명합니다.

MariaDB 강좌 / INNER JOIN으로 서로 연결된 데이터 조회하기

MariaDB 강좌 / INNER JOIN으로 서로 연결된 데이터 조회하기

고객과 주문을 INNER JOIN으로 연결하고 결과 한 행의 의미를 확인합니다. ON과 WHERE, 테이블 별칭, 일대다로 늘어나는 행과 조건 없는 곱집합을 비교합니다.