AD JB Toolbox 01

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

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

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

덤프에 CREATE DATABASE·USE·완전 수식된 객체명이 들어 있으면 연결할 때 지정한 대상 DB와 다른 곳으로 작업할 수 있습니다. 복원 전에 파일을 검토하고 출처·버전·옵션을 확인하세요. 기본 덤프에는 DROP TABLE 같은 문장이 들어 있을 수 있으므로 기존 데이터가 있는 DB에 시험하지 않습니다.

검증 단계 확인 대상 판단 기준
파일 검토 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';
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=C:/mariadb-lab/restore47-source.sql restore47_source

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

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

mariadb --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 도구 조합을 확인합니다. 덤프 파일과 클라이언트 호환성 안내를 참고하세요.

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

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 강좌 / ORDER BY·LIMIT로 정렬하고 조회 범위 제한하기

MariaDB 강좌 / ORDER BY·LIMIT로 정렬하고 조회 범위 제한하기

ORDER BY의 여러 열·방향과 LIMIT·OFFSET을 같은 가격의 상품으로 실습합니다. 동점 해소, 페이지 경계 변화, 마지막 정렬값을 이용한 조회와 NULL 배치를 설명합니다.

MariaDB 강좌 / 사용자 계정 만들고 필요한 권한만 부여하기

MariaDB 강좌 / 사용자 계정 만들고 필요한 권한만 부여하기

사용자·호스트 조합을 확인하고 상품 한 테이블의 SELECT만 허용하는 계정을 만듭니다. 새 연결의 허용·거절 시험, 권한 회수와 기존 계정을 덮어쓰지 않는 정리 절차를 설명합니다.

MariaDB 강좌 / 첫 실습: 상품 테이블을 만들고 데이터를 넣어 조회하기

MariaDB 강좌 / 첫 실습: 상품 테이블을 만들고 데이터를 넣어 조회하기

상품 세 건을 저장하는 전체 SQL로 테이블 생성·입력·조회 과정을 실습합니다. 구조와 행 수, 가격·재고 조건의 예상 결과를 확인하고 반복 입력 오류와 실습 테이블 초기화 범위를 구분합니다.

MariaDB 강좌 / 윈도 함수로 누적 합계와 이전·다음 행 비교하기

MariaDB 강좌 / 윈도 함수로 누적 합계와 이전·다음 행 비교하기

주문별 금액을 누적하고 LAG·LEAD로 이전·다음 행을 비교합니다. ROWS 프레임, 날짜 동점, 결측값과 필터 위치에 따라 누적 지표가 달라지는 조건을 설명합니다.

MariaDB 강좌 / Windows에 MariaDB 설치하고 서버 실행하기

MariaDB 강좌 / Windows에 MariaDB 설치하고 서버 실행하기

Windows MSI 설치에서 서버·클라이언트, 관리자 인증, 서비스와 포트를 설정합니다. SQL 실행을 확인하고 이후 강좌에서 사용할 학습용 계정을 준비하며 시작·접속 오류를 점검합니다.

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

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

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

MariaDB 강좌 / NULL을 올바르게 비교하기: IS NULL·COALESCE

MariaDB 강좌 / NULL을 올바르게 비교하기: IS NULL·COALESCE

NULL·빈 문자열·0을 구분하고 IS NULL·IS NOT NULL과 COALESCE의 역할을 실습합니다. 일반 비교에서 빠지는 NULL 행, NULL-safe 비교와 NOT IN 목록의 함정을 설명합니다.

MariaDB 강좌 / 인덱스 만들기: 단일·복합 인덱스와 열 순서

MariaDB 강좌 / 인덱스 만들기: 단일·복합 인덱스와 열 순서

기존 키를 조회한 뒤 고객·날짜 복합 인덱스를 만들고 같은 조회 결과를 확인합니다. 열 순서·범위·커버링, 쓰기 비용·중복 키·외래키 지원 인덱스의 주의점을 설명합니다.

MariaDB 강좌 / WHERE로 조건 지정하기: 비교·AND·OR·IN·BETWEEN·LIKE

MariaDB 강좌 / WHERE로 조건 지정하기: 비교·AND·OR·IN·BETWEEN·LIKE

상품 가격·분류·재고·이름으로 WHERE 조건을 실습합니다. AND·OR 괄호 차이, IN 목록, BETWEEN 경계, LIKE 와일드카드와 실제 퍼센트 검색을 예상 행 번호로 확인합니다.

MariaDB 강좌 / 데이터베이스 만들기: CREATE DATABASE·USE·문자 집합

MariaDB 강좌 / 데이터베이스 만들기: CREATE DATABASE·USE·문자 집합

shopcourse 데이터베이스를 만들고 현재 연결의 작업 대상으로 선택합니다. utf8mb4와 collation, 기존 DB에서 IF NOT EXISTS의 한계, 권한·문자 설정 확인을 예제로 설명합니다.