대용량 테이블 단위 복구: logical extract와 transportable tablespace
MySQL에서 대용량 테이블을 논리 추출 또는 tablespace 반입으로 복구하는 원리와 선택 기준, 일관성·호환성·검증 절차를 정리한다.
잘못 삭제한 테이블 하나를 되살리기 위해 운영 인스턴스 전체를 과거 시점으로 되돌리면, 사고 이후 다른 테이블에 정상적으로 쌓인 변경까지 잃을 수 있다. 테이블 단위 복구의 핵심은 과거의 일관된 원본을 별도 환경에 확보하고, 필요한 데이터만 현재 서비스에 안전하게 반영하는 것이다.
대용량에서는 추출 방법에 따라 복구 시간이 크게 달라진다. 논리 추출(logical extract)은 행을 읽어 SQL이나 적재 파일로 옮기고, transportable tablespace는 InnoDB의 물리 페이지를 옮긴다. 그러나 물리 복사가 빠르다는 이유만으로 모든 테이블에 적용할 수는 없다. 스토리지 배치, 서버 버전, DDL 이력, 잠금 허용 시간과 업무 관계를 함께 판단해야 한다.
이 글은 MySQL 8.0을 기준으로 설명한다. 기능 실험은 동일한 MySQL Community 8.0.46 두 인스턴스에서 수행했다. 1,000행 규모의 논리 전체 추출·조건부 추출·물리 반입과 정의 불일치 실패를 확인했으며, 대용량 처리량이나 Aurora의 실제 복구 시간은 측정하지 않았다. MySQL 8.4에 적용할 때에도 해당 버전의 반입 제한과 도구 호환성을 다시 확인해야 한다.
1. 테이블을 옮기기 전에 복구 시점을 결정한다
현재 원본에서 내보내기를 수행한다고 이미 삭제된 행이 복원되는 것은 아니다. 복구 데이터의 출처는 보통 다음 중 하나다.
- 사고 이전 논리 백업 또는 정상 상태를 보존한 지연 replica
- 물리 백업을 별도 서버에서 복원하고 필요한 시점까지 로그를 적용한 복구 인스턴스
- Aurora의 특정 시점 복원으로 생성한 별도 DB 클러스터
원본 복구 시점은 업무 트랜잭션의 경계와 맞아야 한다. 주문 테이블은 과거 상태인데 결제와 재고는 현재 상태라면, 각 테이블은 읽을 수 있어도 업무적으로는 잘못된 조합이다. 따라서 먼저 “테이블 전체 교체”, “삭제된 키만 복구”, “특정 값만 보정” 중 무엇을 할지 정한다. 테이블 전체를 반입하는 방법과 현재 테이블 전체를 교체하는 결정은 별개다.
flowchart TD
A[사고 범위와 복구 시점 확정] --> B[별도 환경에 정상 원본 확보]
B --> C{필요한 복구 범위}
C -->|일부 행 또는 값| D[조건부 논리 추출]
C -->|테이블 전체| E{물리 반입 조건 충족}
E -->|아니오| F[전체 논리 추출]
E -->|예| G[export 잠금 후 파일 복사와 import]
D --> H[격리된 복구 테이블에서 검증]
F --> H
G --> H
H --> I[현재 변경과 충돌 및 업무 관계 대조]
I --> J[쓰기 통제 후 반영과 되돌리기 경로 유지]
2. 논리 추출과 물리 반입은 비용의 발생 지점이 다르다
| 구분 | 논리 추출 | Transportable tablespace |
|---|---|---|
| 이동 단위 | 행의 컬럼 값과 DDL | file-per-table tablespace의 페이지와 메타데이터 |
| 대상 선택 | 조건식으로 일부 행을 추출할 수 있음 | 기본적으로 테이블 또는 지원되는 partition 단위 |
| 원본 작업 | 행 읽기, 값 직렬화, 긴 일관 읽기 | export를 위한 페이지 반영과 잠금, 파일 복사 |
| 대상 작업 | SQL 해석, 행 삽입, 인덱스 구성, 로그 기록 | 정의 확인, 페이지 검사·조정, tablespace 연결 |
| 유연성 | 이기종 환경·스키마 보정에 상대적으로 유리 | 같은 버전·페이지 크기·정의 등 엄격한 조건 |
| 파일시스템 접근 | 일반적으로 불필요 | 원본과 대상의 데이터 파일 접근 필요 |
논리 복구는 파일 전송이 끝나도 복구가 끝나지 않는다. 대상이 행을 삽입하면서 인덱스를 유지하고 redo를 기록하며, 설정에 따라 binlog도 생성한다. 긴 트랜잭션과 replica 적용 지연도 고려해야 한다. --quick은 클라이언트가 결과를 한꺼번에 메모리에 쌓는 부담을 줄이지만, 복원 서버의 인덱스 비용을 없애지는 않는다.
물리 반입은 기존 B+Tree 페이지를 활용하므로 행별 SQL 재실행을 피할 수 있다. 그렇다고 단순한 파일명 변경이나 상수 시간 작업은 아니다. 파일 복사 자체가 크기에 비례하며, 반입 과정의 페이지 검사와 메타데이터 조정에도 시간이 든다. 원본 파일의 빈 공간도 전송량에 포함될 수 있다. 양쪽 모두 정상 원본 준비 → 전송 → 적재·반입 → 데이터 검증 → 서비스 전환을 포함한 전체 경과 시간으로 비교해야 한다.
3. 반입 가능 여부는 현재 설정과 실제 배치를 함께 확인한다
innodb_file_per_table=ON은 새 테이블의 기본 배치에 관한 설정이지, 기존 모든 테이블이 개별 .ibd 파일에 있다는 증거가 아니다. 실제 tablespace 종류와 테이블 정의를 확인해야 한다. 다음은 운영 데이터를 건드리지 않는 폐기용 실험 환경을 전제로 한 준비 SQL이다. recovery_src가 없는 별도 서버에서 실행한다.
CREATE DATABASE recovery_src;
CREATE TABLE recovery_src.orders (
id BIGINT NOT NULL PRIMARY KEY,
amount DECIMAL(12,2) NOT NULL,
payload VARCHAR(32) NOT NULL,
KEY ix_amount(amount)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO recovery_src.orders
WITH RECURSIVE seq AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM seq WHERE n < 1000
)
SELECT n, n * 1.25, CONCAT('row-', LPAD(n, 4, '0'))
FROM seq;
SELECT COUNT(*) AS row_count, MIN(id) AS min_id,
MAX(id) AS max_id, SUM(amount) AS total_amount
FROM recovery_src.orders;
실행 결과(MySQL 8.0.x):
mysql> CREATE DATABASE recovery_src;
Query OK, 1 row affected (0.00 sec)
mysql> CREATE TABLE recovery_src.orders (
-> id BIGINT NOT NULL PRIMARY KEY,
-> amount DECIMAL(12,2) NOT NULL,
-> payload VARCHAR(32) NOT NULL,
-> KEY ix_amount(amount)
-> ) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO recovery_src.orders
-> WITH RECURSIVE seq AS (
-> SELECT 1 AS n
-> UNION ALL
-> SELECT n + 1 FROM seq WHERE n < 1000
-> )
-> SELECT n, n * 1.25, CONCAT('row-', LPAD(n, 4, '0'))
-> FROM seq;
Query OK, 1000 rows affected (0.01 sec)
Records: 1000 Duplicates: 0 Warnings: 0
mysql> SELECT COUNT(*) AS row_count, MIN(id) AS min_id,
-> MAX(id) AS max_id, SUM(amount) AS total_amount
-> FROM recovery_src.orders;
+-----------+--------+--------+--------------+
| row_count | min_id | max_id | total_amount |
+-----------+--------+--------+--------------+
| 1000 | 1 | 1000 | 625625.00 |
+-----------+--------+--------+--------------+
1 row in set (0.00 sec)
다음 진단은 위 실험 테이블의 배치를 확인한다. 운영에서 사용할 때에는 NAME 조건을 실제 스키마와 테이블명으로 바꾼다. SPACE_TYPE='Single'은 file-per-table 배치 확인에 유용하지만, 이것만으로 외래 키·암호화·DDL 이력까지 반입 조건을 통과한 것은 아니다.
SELECT VERSION() AS mysql_version,
@@innodb_file_per_table AS file_per_table,
@@innodb_page_size AS page_size;
SELECT NAME, SPACE_TYPE, ROW_FORMAT, STATE
FROM information_schema.INNODB_TABLESPACES
WHERE NAME = 'recovery_src/orders';
실행 결과(MySQL 8.0.x):
mysql> SELECT VERSION() AS mysql_version,
-> @@innodb_file_per_table AS file_per_table,
-> @@innodb_page_size AS page_size;
+---------------+----------------+-----------+
| mysql_version | file_per_table | page_size |
+---------------+----------------+-----------+
| 8.0.46 | 1 | 16384 |
+---------------+----------------+-----------+
1 row in set (0.00 sec)
mysql> SELECT NAME, SPACE_TYPE, ROW_FORMAT, STATE
-> FROM information_schema.INNODB_TABLESPACES
-> WHERE NAME = 'recovery_src/orders';
+---------------------+------------+------------+--------+
| NAME | SPACE_TYPE | ROW_FORMAT | STATE |
+---------------------+------------+------------+--------+
| recovery_src/orders | Single | Dynamic | normal |
+---------------------+------------+------------+--------+
1 row in set (0.00 sec)
반입 사전 점검에서는 아래 항목을 별도로 확인한다.
- 버전과 페이지 크기: 공식 절차는 다른 인스턴스 간 반입 시 양쪽이 같은 GA 버전일 것을 요구한다.
8.0 계열이라는 큰 분류만으로 호환된다고 판단하지 않는다.innodb_page_size도 같아야 한다. - 실제 DDL:
SHOW CREATE TABLE을 보관하고 컬럼 순서·타입·길이, 문자셋과 collation, 인덱스 정의,ROW_FORMAT등을 대조한다. 외부 데이터 디렉터리를 사용했다면 해당 조건도 확인한다. - 배치와 특수 기능: 이 절차는 file-per-table을 대상으로 한다. system/general tablespace의 테이블에는 그대로 적용하지 않는다. partition은 partition별 파일과 정의를 포함한 별도 절차가 필요하다.
- FULLTEXT와 암호화:
FLUSH TABLES ... FOR EXPORT는 FULLTEXT 인덱스가 있는 테이블을 지원하지 않는다. 인덱스 제거·재생성 등의 별도 계획이 필요하다. 암호화 tablespace는.cfp전송 키 파일과 대상 암호화 구성도 다뤄야 한다. - INSTANT DDL 이력: SQL로 보이는 현재 컬럼 정의만 같다고 내부 이력까지 같은 것은 아니다. 특히 즉시 추가·삭제된 컬럼이 있는 테이블을
.cfg없이 반입하는 것을 일반 복구 절차로 삼으면 안 된다.
이 글의 실험은 비암호화·비partition 테이블이며, 외래 키·FULLTEXT·INSTANT 컬럼 변경이 없는 단순한 경우다.
4. 논리 추출: 전체 교체와 부분 보정을 구분한다
mysqldump --single-transaction은 InnoDB에 일관된 읽기 스냅샷을 사용한다. 추출 중 일반 DML을 전부 정지시키는 방식은 아니지만, 오랜 스냅샷은 undo 정리 지연을 유발할 수 있다. 또한 이 옵션이 DDL 동시 실행까지 안전하게 만드는 것은 아니다. 추출 대상의 ALTER, DROP, RENAME, TRUNCATE 등은 변경 통제로 막는다. 비트랜잭션 엔진이 섞여 있으면 같은 보장을 기대할 수 없다.
다음 명령은 별도로 인증 정보가 설정된 recovery_source, recovery_target login path를 전제로 한다. 대상에는 빈 logical_lab, partial_lab 스키마를 먼저 준비한다. 실험에서는 같은 덤프 옵션으로 실제 파일을 만들고, 별도 인스턴스의 빈 스키마에 적재했다. 인증 방법과 파일 경로는 환경에 맞게 조정해야 한다.
mysqldump --login-path=recovery_source \
--single-transaction --quick \
--no-tablespaces --set-gtid-purged=OFF \
--skip-add-drop-table --skip-triggers \
recovery_src orders > orders-full.sql
mysql --login-path=recovery_target logical_lab < orders-full.sql
mysqldump --login-path=recovery_source \
--single-transaction --quick \
--no-tablespaces --set-gtid-purged=OFF \
--skip-add-drop-table --skip-triggers \
--where='id BETWEEN 401 AND 600' \
recovery_src orders > orders-partial.sql
mysql --login-path=recovery_target partial_lab < orders-partial.sql
명령 사이에는 종료 코드를 확인한다. 덤프가 실패했는데 뒤의 적재를 실행해서는 안 된다. 자동화에서는 실패 즉시 중단하도록 구성하고, 출력 파일이 있다는 사실만으로 백업 성공을 판정하지 않는다.
여기서는 --databases를 사용하지 않아 대상 스키마를 명령행에서 지정한다. 그래도 실제 덤프에 원래 DB를 참조하는 뷰·프로그램·트리거 정의가 들어 있으면 별도 검토가 필요하다. --skip-add-drop-table은 기존 테이블을 자동으로 지우지 않게 하는 제한일 뿐, 운영 대상 선택 실수를 모두 막는 장치는 아니다.
--set-gtid-purged=OFF는 이 부분 덤프를 넣으면서 원본 서버 전체의 GTID 실행 이력을 함께 선언하지 않도록 하기 위한 선택이다. 이 파일을 복제 초기화나 PITR의 기준 백업으로 그대로 사용한다는 뜻은 아니다. --no-tablespaces 역시 물리 tablespace 운반 옵션이 아니라 관련 DDL 출력과 권한 요구를 줄이는 옵션이다.
실험에는 트리거가 없었고 --skip-triggers를 명시했다. 운영에서는 트리거를 불필요한 객체로 취급해서는 안 된다. 격리된 복구 테이블에는 부작용을 일으키는 트리거를 자동 설치하지 않고, 서비스에 필요한 원래 트리거·권한·의존 객체를 별도 목록으로 보존하고 반영한다.
조건부 추출은 데이터량을 줄일 수 있지만, 일부 데이터만 있는 테이블을 전체 원본처럼 사용하면 안 된다. 범위가 인덱스로 좁혀지는지 확인하고, 여러 번의 덤프는 각각 다른 스냅샷일 수 있음을 기억한다. 업무적으로 같은 시점이 필요한 여러 조각은 일관된 원본을 고정하거나 일관 스냅샷을 공유하는 도구로 추출한다.
5. 물리 반입: export 세션을 유지하는 것이 핵심이다
InnoDB가 실행 중인 원본의 .ibd만 임의로 복사하면 메모리에 있는 변경이나 복사 중 변경과 정합성이 어긋날 수 있다. FLUSH TABLES ... FOR EXPORT는 대상 테이블을 내보내기에 적합한 상태로 만들고, 변경 페이지를 디스크에 반영하며, 스키마 검사용 .cfg를 생성한다. 확보한 잠금은 복사 중 변경을 막는 역할을 한다.
파일 복사가 끝날 때까지 같은 연결을 열어 두어야 한다. mysql -e 'FLUSH TABLES ... FOR EXPORT'만 실행하고 프로세스가 종료된 뒤 복사하는 방식은 잘못된 순서다. 연결이 닫히면 잠금이 풀리고 .cfg도 제거된다. 대용량 파일의 복사 시간이 길면 쓰기 중단 시간도 길어질 수 있으므로, 가능하면 운영 writer가 아니라 격리된 복구 원본에서 수행한다.
다음은 두 서버에서 실제 수행한 순서다. 아래 SQL 작업 순서는 파일 작업과 세션 유지가 필요한 절차이므로, 하나의 SQL 파일로 합쳐 실행하지 않는다.
| 단계 | 실행 위치 | 수행 내용과 통과 기준 |
|---|---|---|
| 1 | 대상 | 빈 physical_lab에 원본과 동일한 orders 정의를 생성한다. 이번 실험은 3절의 DDL에서 스키마명만 변경했다. |
| 2 | 대상 | ALTER TABLE physical_lab.orders DISCARD TABLESPACE;로 대상 빈 테이블의 tablespace를 버린다. |
| 3 | 원본 세션 A | FLUSH TABLES recovery_src.orders FOR EXPORT; 완료를 확인하고 연결을 유지한다. |
| 4 | 파일 작업 세션 B | 원본의 orders.ibd, orders.cfg를 함께 대상 스키마 디렉터리로 복사한다. 복사 완료와 소유권·접근 권한을 확인한다. |
| 5 | 원본 세션 A | UNLOCK TABLES;로 잠금을 해제한다. |
| 6 | 대상 | ALTER TABLE physical_lab.orders IMPORT TABLESPACE;를 실행한다. |
| 7 | 대상 | 전체 행과 컬럼 값, 인덱스 접근, 업무 관계를 점검한다. 필요한 통계 갱신과 실행 계획 검토 후 전환을 준비한다. |
DISCARD TABLESPACE는 데이터를 버리는 동작이다. 원본이나 현재 서비스 중인 정상 테이블에 실행해서는 안 된다. 반입 실패 시 다시 만들 수 있는 격리된 대상에서만 수행한다. 파일 소유권은 대상 mysqld 계정 기준으로 맞추며, 디렉터리 전체에 무차별적인 권한 변경을 적용하지 않는다.
이번 파일 전송은 원본에서 잠금이 유지된 동안 두 파일을 tar 스트림으로 묶고 대상 디렉터리에 풀어 수행했다. 전송 도구가 무엇이든 잠금 해제 전에 일관된 복사본을 확보해야 한다. 원격 전송의 암호화, 파일 해시 검증, 대용량 재전송 정책은 별도 운영 항목이다.
외래 키가 있는 경우에는 추가 경계가 있다. DISCARD 전에 해당 세션의 foreign_key_checks 조정이 필요할 수 있지만, 이를 껐다고 참조 관계가 올바르게 복구되는 것은 아니다. IMPORT TABLESPACE는 반입 데이터의 외래 키 정합성을 검증하지 않는다. 관련 테이블을 같은 논리 시점에 확보하고 부모 누락·자식 고아 행을 직접 검사해야 한다. 설정을 다시 켜는 것만으로 이미 들어온 모든 행을 소급 검증한다고 가정해서도 안 된다.
.cfg가 없는데 반입에 성공하는 제한적인 경우도 있다. 그러나 스키마 검사를 생략한 성공은 올바른 복구의 증명이 아니다. 특히 INSTANT 컬럼 변경이 있는 경우에는 공식 문서가 정의되지 않은 동작을 경고한다. 일상적인 복구 계획은 .cfg가 포함된 정상 export 경로를 기준으로 수립한다.
6. 실제 왕복 검증: 성공과 의도한 실패를 함께 확인한다
동일 버전의 폐기용 두 인스턴스에 3절과 같은 1,000행 원본을 만들었다. 전체 논리 덤프, 키 범위 401~600의 부분 덤프, .ibd와 .cfg 파일 복사를 완료한 뒤 원본에서 id=500 한 행을 삭제했다. 물리 반입은 삭제 이후 대상에서 수행했다. 따라서 반입본이 삭제 후 원본을 따라가는 것이 아니라 복사 시점의 데이터를 보존하는지도 확인할 수 있다.
복원 비교 결과(MySQL 8.0.46, 실제 조회값):
| 대상 | 행 수 | 최소 id | 최대 id | amount 합계 |
|---|---|---|---|---|
| 원본: 복사 이후 한 행 삭제 | 999 | 1 | 1000 | 625000.00 |
| 전체 논리 복원본 | 1000 | 1 | 1000 | 625625.00 |
| 부분 논리 복원본 | 200 | 401 | 600 | 125125.00 |
| 물리 반입 복원본 | 1000 | 1 | 1000 | 625625.00 |
이 표의 집계만 비교한 것은 아니다. 삭제 전 기준 데이터를 id 순으로 정렬하여 모든 행의 id, amount, payload를 복원본과 직접 대조했다. 전체 논리 복원본과 물리 반입본은 기준 1,000행 전부가 일치했고, 부분 복원본은 선택 범위의 200행 전부가 일치했다. 원본은 삭제 이후 기준 데이터와 다름을 확인했다. 원본의 .cfg가 잠금 해제 후 제거되는 것도 확인했다.
실패 경로도 시험했다. 별도 대상 mismatch_lab.orders에서 payload만 VARCHAR(64)로 생성하고, 정상 원본의 VARCHAR(32) 파일과 .cfg를 반입했다. 실제 클라이언트 결과는 다음과 같았으며, 프로세스가 실패 종료하는 것을 검사했다.
mysql> ALTER TABLE mismatch_lab.orders IMPORT TABLESPACE;
ERROR 1808 (HY000) at line 1: Schema mismatch (Column payload precise type mismatch.)
이 결과는 해당 정의 차이를 .cfg 기반 검사로 차단했다는 뜻이다. 모든 종류의 정의 불일치가 자동으로 검출된다는 뜻은 아니다. 예를 들어 partition 정의 차이는 .cfg 검사의 제한이 있으므로 별도 대조가 필요하다.
검증 범위의 한계: 이 실험은 작은 정적 데이터의 서버 간 이동과 복사 시점 보존을 검증했다. 실제 백업에서 사고 시점까지 PITR하는 과정, 손상된 페이지 복구, 장애 중 export, 외래 키·암호화·partition·INSTANT DDL, 운영 트래픽 전환은 시험하지 않았다. 물리 반입이 특정 용량에서 몇 배 빠르다는 수치도 이 실험으로 주장할 수 없다.
7. 복원 성공과 운영 반영 성공은 다르다
복구 테이블이 열렸다는 사실은 서비스로 넘겨도 된다는 뜻이 아니다. 대용량 테이블에서는 다음 네 가지를 독립적으로 판단한다.
- 물리·정의 검증: import 오류, 테이블 정의, 인덱스와 대상 객체 목록을 확인한다. 같은 행 수인데 컬럼 값이 잘못된 경우도 탐지할 수 있어야 한다.
- 데이터 검증: PK 구간별 행 수와 값 대조를 수행한다. 전체 비교가 어려우면 결정적인 직렬화와 구간별 해시 등 검증 방식을 설계하되,
COUNT(*)나 합계 하나로 무결성을 확정하지 않는다. - 업무 검증: 현재 테이블과 복구본의 키 충돌, 삭제된 행의 부모 데이터, 사고 이후 정상 수정, 주문·결제·재고 간 불변조건을 검토한다.
- 전환 검증: 대상 쓰기를 통제하고 메타데이터 잠금 대기, 참조하는 객체, 트리거, 권한, 애플리케이션 재시도와 되돌리기 절차를 확인한다.
삭제된 일부 행만 필요하다면 물리 반입본에서도 해당 행을 논리적으로 추출해 최종 반영할 수 있다. 반대로 전체 테이블을 무조건 바꾸면 사고 이후 정상 변경을 잃을 수 있다. RENAME TABLE의 이름 변경 자체가 원자적이어도 업무 상태의 일관성과 모든 의존 객체의 의미까지 자동으로 보장하지는 않는다.
INSERT IGNORE나 무조건적인 upsert로 충돌을 숨기는 것도 위험하다. 복구본의 과거 값과 현재 값이 다르면 어떤 값을 보존할지 명시적으로 정해야 한다. 최종 적용 전 현재 상태의 되돌리기 자료를 확보하고, 원래 데이터와 복구본을 검증 완료까지 보존한다.
8. Aurora MySQL에서는 논리 추출 경로를 중심으로 설계한다
Aurora의 특정 시점 복원은 원래 클러스터의 테이블 하나를 되감는 작업이 아니라 새 DB 클러스터를 만드는 작업이다. 정상 시점으로 복원한 클러스터를 격리하고, 대상 테이블 또는 필요한 행을 논리 추출하여 현재 클러스터의 복구용 스키마로 가져오는 방식이 기본적인 접근이다.
Aurora는 사용자가 데이터 디렉터리의 .ibd, .cfg 파일을 복사하고 소유권을 조정하는 일반 서버가 아니다. 따라서 이 글의 Community MySQL용 파일 단위 반입 절차를 Aurora endpoint에 그대로 적용하지 않는다. S3 기반 이관 등 관리형 기능도 목적과 지원 조건이 다르므로, 임의의 단일 테이블 tablespace 반입과 같은 기능으로 간주하지 않는다.
시간 계획에는 복원 가능 시점 확인, 새 클러스터와 연결 가능한 DB 인스턴스 준비, 파라미터·보안 설정 확인, 대용량 읽기와 적재, 검증을 포함한다. AWS 공식 문서는 복원된 클러스터에 기본 파라미터 그룹이 연결될 수 있으므로 사용자 정의 그룹을 필요에 따라 지정하도록 안내한다. 데이터가 복구되어도 문자셋·시간대·SQL 모드 등 주변 조건이 의도와 맞는지 별도로 확인한다.
이 글에서는 Aurora 클러스터를 생성하거나 과금이 발생하는 복구 실험을 수행하지 않았다. 관리형 복원의 동작 범위는 공식 문서를 근거로 설명했으며, 로컬 왕복 실험을 Aurora 검증 결과로 확대하지 않는다.
9. 선택 기준과 실행 전 점검표
일부 행이나 값을 보정해야 하거나 파일 접근이 없는 환경이라면 논리 추출이 우선이다. 테이블 전체가 필요하고, 동일 버전의 file-per-table 구성·정의 일치·파일 접근·export 잠금 시간을 확보할 수 있다면 물리 반입을 후보로 삼는다. 대용량일수록 도구 이름보다 실측한 전체 복구 시간과 검증 가능한 경계가 선택 기준이어야 한다.
- export 연결 유지와 파일 복사 완료 확인,
.cfg -
DISCARD TABLESPACE
10. 정리
논리 추출은 필요한 데이터를 고르는 유연성을 제공하고, transportable tablespace는 조건을 만족하는 테이블의 물리 구조를 재사용한다. 어느 쪽도 복구 시점의 올바름이나 현재 서비스와의 충돌 해결을 대신하지 않는다.
대용량 테이블 복구의 완료 조건은 “명령이 성공했다”가 아니라, 정상 시점의 데이터를 격리된 대상에 확보하고, 값과 관계를 검증하며, 현재의 정상 변경을 훼손하지 않고 반영할 수 있음이다. 이후 백업 보존·복구 훈련과 스키마 변경 절차를 설계할 때에도, 단일 테이블을 실제로 꺼내 복원할 수 있는지와 특수 DDL 이력이 반입 경로를 제한하는지를 함께 점검해야 한다.
참고 문서
- MySQL 8.0 공식 문서: Importing InnoDB Tables — 버전·페이지 크기 전제, export 연결 유지,
.cfg와 INSTANT 컬럼, 외래 키 및 FULLTEXT 제한. - MySQL 8.0 공식 문서: mysqldump — 일관 스냅샷, 조건부 추출, 부분 덤프의 GTID와 객체 옵션.
- Amazon Aurora 공식 문서: 특정 시점으로 DB 클러스터 복원 — 새 클러스터 생성과 복원 가능 시점, 파라미터 그룹 및 인스턴스 준비.