---
title: "XtraBackup prepare 단계: redo 적용과 일관된 백업 완성"
description: "XtraBackup prepare의 redo 적용과 미커밋 트랜잭션 롤백, 증분 병합 순서와 LSN 연결을 실제 복원 결과로 확인한다."
tags: [ MySQL, 백업복구, InnoDB, 운영 ]
image: "mysql-report-bg.png"
published: "2026-09-27"
updated: "2026-09-27"
author: "MySQL 기술 노트"
source_url: ""
---

## 1. 백업 파일이 있다는 것과 복원할 수 있다는 것은 다르다

온라인 물리 백업은 실행 중인 서버의 파일을 시간차를 두고 복사한다. 먼저 복사한 페이지와 나중에 복사한 페이지가 서로 다른 변경 시점을 담을 수 있으므로, 백업 명령이 성공했다고 해서 복사된 데이터 파일이 곧바로 기동 가능한 상태가 되는 것은 아니다. XtraBackup의 `prepare`는 이 파일 집합에 복구 절차를 적용하여 일관된 백업을 완성하는 단계다.

운영에서 중요한 구분은 **파일 수집 완료**, **최종 prepare 완료**, **복원 서버 기동 및 데이터 검증 완료**다. 세 상태를 같은 성공 표시로 관리하면 재해가 발생한 뒤에야 누락된 redo, 잘못된 증분 연결, 복호화 키 부재를 발견할 수 있다. 특히 증분 백업을 합칠 계획이 있는데 전체 백업에 최종 롤백을 먼저 수행하면 이후 증분 적용이 불가능해질 수 있다.

이 글은 MySQL 8.0과 Percona XtraBackup 8.0을 기준으로 redo 적용과 롤백의 차이를 설명한다. 실제 검증은 **MySQL 8.0.46 / XtraBackup 8.0.35-36**에서 전체 백업과 증분 백업을 생성하고, 단계별 prepare를 거쳐 별도 서버에 복원하는 방식으로 수행했다. 8.4 계열에는 해당 계열의 지원 도구와 호환성 기준을 적용해야 하며, 이 실험을 다른 버전의 호환성 보증으로 해석해서는 안 된다.

## 2. prepare 내부에서 일어나는 두 가지 복구

### 2.1 redo 적용은 커밋된 SQL만 다시 실행하는 작업이 아니다

InnoDB는 데이터 페이지 변경과 관련된 redo를 기록한다. 데이터 파일의 페이지에는 각 페이지의 변경 진척을 나타내는 LSN이 들어 있고, 복구 과정은 이 정보와 redo 기록을 이용해 필요한 변경을 반영한다. XtraBackup은 온라인 복사 중 필요한 redo도 수집하여 서로 다른 시점에 읽힌 파일을 복구할 재료를 확보한다.

`prepare`는 XtraBackup에 포함된 수정된 InnoDB 코드를 사용하여 **백업 디렉터리의 파일**에 crash recovery 성격의 처리를 수행한다. 원본 서버에 SQL을 보내서 데이터를 다시 조회하거나, binlog에서 커밋된 SQL을 골라 실행하는 방식이 아니다. 따라서 백업 수집이 끝났다면 원본 서버에 연결하지 않는 별도 준비 서버에서도 수행할 수 있다.

redo에는 나중에 커밋되는 트랜잭션뿐 아니라 복구 경계까지 커밋하지 않은 트랜잭션의 변경도 포함될 수 있다. 데이터 페이지 자체에도 미커밋 변경이 기록될 수 있다. **redo를 모두 적용했다는 사실만으로 미커밋 변경이 사라지는 것은 아니다.**

### 2.2 undo를 이용한 롤백이 최종 트랜잭션 상태를 정리한다

최종 prepare는 redo 적용에 이어 복구 대상 상태에서 미완료인 트랜잭션을 정리한다. 이때 undo를 이용하여 커밋되지 않은 변경을 되돌린다. 전체 백업 하나를 복원할 경우에는 일반적으로 `--prepare` 한 번으로 이 절차를 진행한다.

증분 체인을 준비할 때는 판단 시점이 다르다. 전체 백업을 찍을 때 열려 있던 트랜잭션이 다음 증분 백업을 찍기 전에 커밋될 수 있다. 전체 백업에서 이 트랜잭션을 먼저 되돌려 버리면, 뒤에 이어지는 증분이 전제하는 상태와 달라진다. 그래서 중간 단계에서는 `--apply-log-only`로 롤백을 미룬다.

```mermaid
flowchart TD
    A[전체 백업 파일과 수집한 redo] --> B{추가 증분을 병합하는가}
    B -->|아니요| C[최종 prepare: redo 적용과 미커밋 롤백]
    B -->|예| D[apply-log-only: 롤백 보류]
    D --> E[LSN 연결 확인 후 증분 delta 병합과 redo 적용]
    E --> F{다음 증분이 있는가}
    F -->|예| E
    F -->|아니요| C
    C --> G[준비된 백업을 빈 datadir에 복사]
    G --> H[별도 서버 기동과 업무 데이터 검증]
```

`--apply-log-only`는 “커밋된 트랜잭션만 적용”하는 옵션이 아니라 **prepare의 롤백 단계를 건너뛰는 옵션**이다. 또한 이 상태를 무조건 기동 불가능한 백업이라고 설명하는 것도 정확하지 않다. Percona 문서는 redo 적용 후 롤백을 생략한 백업을 복원하면 서버 기동 과정에서 미완료 롤백을 수행할 수 있다고 설명한다. 다만 운영 절차에서는 최종 prepare까지 미리 완료해 복구 시간과 상태를 명확히 관리하는 편이 유리하다. 이 글의 복원 실험도 최종 prepare를 완료한 뒤 기동했다.

## 3. LSN과 체크포인트 파일을 읽는 기준

`xtrabackup_checkpoints`는 백업의 종류와 연결 경계를 확인하는 핵심 메타데이터다. 단, 메타데이터 값이 정상이라는 사실만으로 모든 페이지와 업무 데이터가 정상임을 증명하지는 못한다.

| 항목 | 의미와 판단 기준 |
|---|---|
| `backup_type` | 수집된 전체 백업, 증분 백업, redo 적용 상태, 최종 준비 상태를 구분한다. 실제 문자열은 도구 버전과 수행 단계에서 확인한다. |
| `from_lsn` | 증분 백업이 시작하는 기준 LSN이다. 바로 앞 백업의 `to_lsn`과 연결되어야 한다. |
| `to_lsn` | 해당 백업의 체크포인트 경계이자 다음 증분 연결에 사용하는 기준이다. |
| `last_lsn` | 수집한 redo가 도달한 마지막 LSN이다. `to_lsn`보다 클 수 있으며, 다음 증분 연결에 임의로 대신 사용하지 않는다. |

이번 실험에서는 전체 백업의 `to_lsn`이 `29641616`, `last_lsn`이 `29641947`이었다. 두 값이 다르다는 사실 자체는 백업 오류가 아니다. 다음 증분의 `from_lsn`은 **29641616**으로 전체 백업의 `to_lsn`과 연결되었다. LSN은 시간이나 GTID가 아니므로 “이 숫자가 같으니 같은 시각의 업무 상태다”라고 판단해서는 안 된다.

최종 prepare 로그의 InnoDB shutdown LSN이 체크포인트 파일의 `to_lsn`보다 커질 수도 있다. 복구와 롤백 과정의 내부 변경을 함께 고려해야 한다. 증분 연결 확인에는 백업 메타데이터의 정해진 필드를 사용하고, 로그 마지막 숫자를 새로운 연결 기준으로 만들어서는 안 된다.

## 4. 실험: 백업을 가로지르는 커밋과 끝까지 남은 미커밋 변경

### 4.1 버전과 기본 조건 확인

다음은 MySQL 8.0.30 이상에서 실행할 수 있는 환경 확인 쿼리다. `innodb_redo_log_capacity`는 redo 공간 설정이지 prepare 완료 시간이나 백업에 필요한 redo 크기의 직접 측정값이 아니다.

```sql
SELECT VERSION() AS mysql_version,
       @@innodb_page_size AS page_size_bytes,
       @@innodb_redo_log_capacity AS redo_capacity_bytes;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SELECT VERSION() AS mysql_version,
    ->        @@innodb_page_size AS page_size_bytes,
    ->        @@innodb_redo_log_capacity AS redo_capacity_bytes;

+---------------+-----------------+---------------------+
| mysql_version | page_size_bytes | redo_capacity_bytes |
+---------------+-----------------+---------------------+
| 8.0.46        |           16384 |           104857600 |
+---------------+-----------------+---------------------+
1 row in set (0.00 sec)
```

SQL 실행 결과는 별도의 폐기용 SQL 검증 인스턴스에서 확인한 값이다. 아래 물리 백업 실험 서버는 redo 용량을 64MiB로 설정했다. SQL 검증 인스턴스와 물리 백업 서버의 설정값을 혼동하지 않는다.

실험은 외부 포트를 열지 않은 폐기용 컨테이너와 전용 디렉터리에서 수행했다. XtraBackup에는 원본 datadir의 읽기 접근과 백업 디렉터리의 쓰기 접근을 부여했다. 준비 단계에서는 원본 MySQL 컨테이너를 제거하고 백업 파일만 사용했다. 운영 계정 권한 설계, 암호화 백업, 압축 해제, 동시 DDL, 대용량 부하 및 Aurora 복원은 이 실험 범위에 포함하지 않았다.

초기 데이터는 다음과 같다. `prepare_lab`은 실습 전용 이름이며, 운영 서버가 아닌 빈 테스트 인스턴스에서만 실행한다. 실제 물리 실험과 SQL 검증에서 같은 테이블 정의와 초기 행을 사용했다.

```sql
CREATE DATABASE prepare_lab;
CREATE TABLE prepare_lab.account (
    id INT PRIMARY KEY,
    balance INT NOT NULL
) ENGINE=InnoDB;
INSERT INTO prepare_lab.account VALUES (1,100),(2,200),(3,300);
SELECT id, balance FROM prepare_lab.account ORDER BY id;
```

실행 결과(MySQL 8.0.x):

```text
mysql> CREATE DATABASE prepare_lab;

Query OK, 1 row affected (0.00 sec)

mysql> CREATE TABLE prepare_lab.account (
    ->     id INT PRIMARY KEY,
    ->     balance INT NOT NULL
    -> ) ENGINE=InnoDB;

Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO prepare_lab.account VALUES (1,100),(2,200),(3,300);

Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT id, balance FROM prepare_lab.account ORDER BY id;

+----+---------+
| id | balance |
+----+---------+
|  1 |     100 |
|  2 |     200 |
|  3 |     300 |
+----+---------+
3 rows in set (0.00 sec)
```

### 4.2 시간순으로 상태를 만든다

| 순서 | 원본 서버에서 수행한 동작 | 복구 관점의 의미 |
|---|---|---|
| 1 | 세션 A에서 트랜잭션을 열고 id=2를 999로 변경한 채 연결을 유지한다. | 전체 백업 시점에는 아직 미커밋이다. |
| 2 | 전체 백업을 `/lab/base`에 생성한다. | 세션 A의 트랜잭션이 백업 경계를 가로지른다. |
| 3 | 세션 A를 커밋하고, id=3을 330으로 변경하여 커밋한다. | 다음 증분에는 보존해야 할 정상 변경이다. |
| 4 | 세션 B에서 트랜잭션을 열고 id=1을 777로 변경한 채 연결을 유지한다. | 최종 백업 경계에서도 미커밋으로 남길 변경이다. |
| 5 | `/lab/base`를 기준으로 증분 백업을 `/lab/inc1`에 생성한다. | 정상 커밋과 미커밋 변경이 함께 존재한다. |
| 6 | 다른 연결에서 커밋된 전체 행을 기준 데이터로 저장한다. 이후 세션 B를 롤백하고 id=3을 삭제·커밋한다. | 백업 후 삭제가 복원본에 섞이지 않는지도 구분한다. |
| 7 | 원본 서버를 제거하고 prepare와 별도 서버 복원을 수행한다. | 원본 재조회 없이 백업 파일로 복구한다. |

세션 A와 B는 각각 `START TRANSACTION` 후 해당 행에 `UPDATE`를 실행한 실제 별도 연결이다. 미커밋 상태를 유지해야 하는 구간에 연결을 닫으면 서버가 롤백하므로 실험 의도가 사라진다. 세션 A는 전체 백업 성공 뒤에만 `COMMIT`, 세션 B는 증분 백업 성공 뒤에만 `ROLLBACK`했다.

다음은 실험에서 실행한 XtraBackup 핵심 명령이다. 컨테이너 실행 및 mount 옵션은 생략했으며, `/lab`과 `/var/lib/mysql`은 **검증 컨테이너 내부 경로**다. `root`는 외부에 노출되지 않는 폐기용 실험의 접속 계정이다. 운영에서는 검증된 최소 권한 계정과 안전한 인증 설정을 별도로 구성해야 한다.

```bash
xtrabackup --backup --host=127.0.0.1 --user=root \
  --datadir=/var/lib/mysql --target-dir=/lab/base --lock-ddl

xtrabackup --backup --host=127.0.0.1 --user=root \
  --datadir=/var/lib/mysql --target-dir=/lab/inc1 \
  --incremental-basedir=/lab/base --lock-ddl
```

두 명령 사이에 위 표의 커밋과 세션 B 갱신을 수행했다. 두 백업 모두 종료 코드 0과 `completed OK!`를 확인했으며, 증분의 `from_lsn`과 전체 백업의 `to_lsn` 일치를 검사했다.

### 4.3 롤백을 보류한 채 병합하고 마지막에 완료한다

```bash
xtrabackup --prepare --apply-log-only \
  --target-dir=/lab/base --use-memory=128M

xtrabackup --prepare --apply-log-only \
  --target-dir=/lab/base --incremental-dir=/lab/inc1 --use-memory=128M

xtrabackup --prepare --target-dir=/lab/base --use-memory=128M
```

이 실험은 **마지막 증분도 redo 적용만 수행한 뒤, 별도 최종 prepare로 롤백을 완료**하는 형태다. 마지막 증분 적용 명령에서 `--apply-log-only`를 생략해 최종 준비까지 수행하는 방식도 공식 문서에 제시되어 있다. 어느 방식을 택하든 중간 증분이 남아 있는데 롤백을 완료해서는 안 된다.

병합 대상은 계속 `/lab/base`다. `/lab/inc1`이 최종 복원 디렉터리로 바뀌는 것이 아니다. 아래 표는 각 단계 직후 체크포인트 파일에서 읽은 실제 값이다. 숫자는 이번 실행의 관측값이며 다른 환경에 재사용하는 설정값이 아니다.

| 단계 | `backup_type` | `from_lsn` | `to_lsn` | `last_lsn` |
|---|---|---:|---:|---:|
| 전체 백업 수집 | `full-backuped` | 0 | 29641616 | 29641947 |
| 증분 백업 수집 | `incremental` | 29641616 | 29644201 | 29644201 |
| 전체 백업에 redo만 적용 | `log-applied` | 0 | 29641616 | 29641947 |
| 증분 병합 후 redo만 적용 | `log-applied` | 0 | 29644201 | 29644201 |
| 최종 prepare 완료 | `full-prepared` | 0 | 29644201 | 29644201 |

최종 prepare 로그에서 시간과 공통 접두어를 제외한 핵심 메시지만 발췌하면 다음과 같다.

```text
This target seems to be already prepared with --apply-log-only.
1 transaction(s) which must be rolled back or cleaned up in total 1 row operations to undo
Starting in background the rollback of uncommitted transactions
Rolling back trx with id 1825, 1 rows to undo
Shutdown completed; log sequence number 29645000
completed OK!
```

미커밋 세션 B의 변경을 정리하는 동작이 로그에 나타난다. 그러나 로그의 성공 문구와 트랜잭션 개수만으로 id=1의 실제 복구 값을 단정하지 않고, 다음 단계에서 전체 행을 비교했다.

### 4.4 copy-back과 별도 기동으로 최종 결과를 확인한다

```bash
xtrabackup --copy-back --target-dir=/lab/base --datadir=/lab/restored
```

`/lab/restored`는 사전에 만든 **비어 있는 별도 datadir**이다. 운영 datadir 위에 덮어쓰는 명령이 아니다. copy-back 완료 후 파일 접근 권한을 확인하고, 이 디렉터리를 datadir로 사용하는 별도 MySQL 8.0.46 서버를 기동했다. 테스트 서버의 기동 성공도 TCP 연결을 통한 `SELECT VERSION()`으로 확인했다.

복원 서버에서 실행한 조회 명령은 다음과 같다. 연결 인증과 접속 대상은 검증 컨테이너 내부 환경을 전제로 한다.

```bash
mysql --protocol=TCP -h127.0.0.1 -uroot -N -B \
  -e 'SELECT * FROM prepare_lab.account ORDER BY id;'
```

실제 실행 결과는 batch 형식이므로 열 제목 없이 표시된다.

```text
1	100
2	999
3	330
```

이 결과를 증분 백업 직후 확보한 기준 데이터의 **전체 행**과 비교하여 일치를 확인했다.

- **id=2의 999가 남았다.** 전체 백업 때는 미커밋이었지만 증분 백업 전에 커밋된 변경을 보존했다.
- **id=1은 100이다.** 증분 백업 경계에서도 미커밋인 777이 최종 복원본에 남지 않았다.
- **id=3의 330이 남았다.** 백업 이후 원본에서 수행한 삭제는 이 백업의 복구 범위 밖이다.

이것은 전체 백업과 증분 하나의 정상 체인에 대한 물리 복원 검증이다. 잘못된 체인의 모든 실패 유형, 실제 서버 손실 대응 시간, binlog를 이용한 PITR, 다른 서버 버전으로의 복원까지 검증한 결과는 아니다.

## 5. prepare를 운영 절차에 넣을 때의 판단 기준

### 5.1 원본 백업과 준비 작업본을 분리한다

prepare는 백업 디렉터리를 읽기만 하는 검사가 아니라 **파일을 변경하는 작업**이다. 원본 백업을 보존하고 별도 작업본을 준비해야 실패 후 같은 재료로 다시 시도할 수 있다. 증분 디렉터리 역시 재사용이 무조건 안전하다고 가정하지 않는다. Percona는 동일한 증분 디렉터리를 여러 번 prepare에 사용하지 말라고 명시한다. 여러 복구 후보를 시험하려면 보존 원본에서 각 시도용 디렉터리를 따로 구성한다.

준비 중 강제 종료가 발생했다면 마지막으로 남은 `backup_type` 값만 보고 성공 처리하지 않는다. 공식 문서는 중단된 prepare의 백업 유효성을 보장하지 않는다. 보존 원본에서 작업본을 다시 만들고 전체 체인을 재검증하는 절차를 기본 복구 경로로 둔다.

### 5.2 준비 시점과 복구 시간을 함께 설계한다

최종 prepare를 미리 수행하면 사고 후 redo 적용과 롤백에 쓸 시간을 줄일 수 있다. 반대로 증분을 계속 합칠 작업본을 최종 준비 상태로 만들어 버리면 이후 증분을 이어 붙일 수 없다. 운영에서는 “계속 전진시키는 체인 작업본”과 “특정 복구 시점의 최종 준비본”을 분리하여 관리하는 방식이 적합하다.

실제 복구 시간에는 백업 전송, 복호화·압축 해제, 증분 병합, redo 적용, 롤백, copy-back, 서버 기동, 데이터 검증과 애플리케이션 전환이 모두 들어간다. 백업을 생성하는 데 걸린 시간만 재서 RTO를 정하면 안 된다. 큰 미커밋 트랜잭션은 준비 또는 기동 중 롤백 부담으로 돌아올 수 있다.

### 5.3 메모리와 병렬도는 병목에 맞추어 조정한다

`--use-memory`는 prepare에서 사용하는 InnoDB 버퍼 풀 크기를 조정하는 옵션이다. 프로세스 전체 메모리 사용량을 그 값 이하로 제한하는 옵션은 아니다. 이 실험의 128M는 작은 테스트 데이터에 맞춘 값이며 운영 권장값이 아니다. 복구 서버의 여유 메모리, 컨테이너 제한, 파일 캐시와 다른 프로세스를 함께 고려한다.

`--parallel`을 높였다고 redo 적용과 롤백의 모든 작업이 같은 비율로 빨라지는 것도 아니다. 공식 문서에 따르면 8.0.35-33부터 prepare 시 증분 `.delta` 파일 병합에 병렬 처리가 적용되며, 파일 단위로 동작한다. 하나의 큰 delta 파일을 여러 스레드가 나눠 처리하는 방식은 아니다. 이 글에서는 병렬 성능을 측정하지 않았다.

## 6. 자주 발생하는 실패와 오해

| 관측 또는 오해 | 점검과 대응 |
|---|---|
| 백업 명령이 성공했으니 복원 준비도 끝났다고 판단한다. | 수집, prepare, 실제 기동·데이터 검증을 서로 다른 상태로 관리한다. |
| 중간 전체 백업에 최종 prepare를 수행했다. | 이후 증분을 억지로 적용하지 않는다. 보존한 원본에서 redo-only 준비를 다시 시작한다. |
| 다음 증분의 `from_lsn`이 앞 백업의 `to_lsn`과 다르다. | 누락·순서 오류·다른 기준 백업 혼입을 조사한다. 메타데이터 숫자를 수동 수정해 통과시키지 않는다. |
| `last_lsn`과 `to_lsn`이 다르므로 손상이라고 판단한다. | redo 수집 범위와 체크포인트 경계를 구분한다. 연결 검사는 정해진 필드로 수행한다. |
| prepare가 파일 또는 키를 찾지 못한다. | 스트림 추출, 압축 해제, 복호화, keyring 접근과 파일 권한 등 선행 조건을 확인한다. |
| 오래 걸리는 prepare를 강제 종료한 뒤 상태 파일만 믿고 복사한다. | 중단된 작업본의 유효성을 단정하지 않는다. 자원과 로그를 조사한 뒤 보존 원본으로 재시도한다. |
| 복원 서버가 기동했으니 업무 데이터도 정상이다. | 핵심 테이블 전체 또는 검증 범위별 행·관계·업무 불변식을 검사한다. 서버 기동은 별도 통과 조건일 뿐이다. |

prepare 성공은 파일 수준 복구가 완료되었다는 중요한 신호지만, 애플리케이션의 논리적 정합성을 자동 보증하지 않는다. 이미 커밋된 잘못된 삭제나 잘못된 금액도 정상 트랜잭션으로 복원될 수 있다. 사고 직전으로 돌아가려면 백업 경계와 binlog 보관·적용 경계를 연결하는 별도의 PITR 절차가 필요하다.

## 7. Aurora MySQL에서는 적용 경계가 다르다

Aurora MySQL은 사용자가 클러스터 스토리지의 datadir에 직접 접근하여 XtraBackup prepare와 copy-back을 수행하는 운영 모델이 아니다. Aurora의 자동 백업, 스냅샷, 시점 복원은 관리형 서비스 기능으로 다루며, 사용자가 복원 시각·보존 기간·복원 클러스터 구성과 검증 절차를 관리한다.

외부 MySQL의 XtraBackup 백업을 S3를 통해 Aurora로 가져오는 이관 기능은 Aurora 자체 백업을 로컬에서 prepare하는 것과 별개의 경로다. 대상 Aurora 버전, 지원되는 소스 버전과 백업 형식 등 이관 기능의 제한을 따로 확인해야 한다. 이 글의 로컬 copy-back 성공을 Aurora 이관 성공으로 확대하지 않는다.

두 환경에 공통으로 적용되는 원칙은 **복구할 수 있는 경계가 어디인지 확인하고 실제 복원된 데이터로 검증한다**는 것이다. Aurora에서도 복원 요청 성공만으로 애플리케이션 연결, 권한, 핵심 데이터와 운영 전환 검증이 끝나는 것은 아니다.

## 8. 발행용 예제를 넘어 운영에 적용하기 전 점검표

- [ ] 원본 MySQL, XtraBackup, 복원 MySQL의 버전 조합이 공식 지원 범위에 있는가?
- [ ] 백업 원본과 prepare 작업본을 분리하고, 작업본 손상 시 재시도할 원본을 보존하는가?
- [ ] 전체 백업과 모든 증분의 순서 및 `to_lsn` → `from_lsn` 연결을 검사했는가?
- [ ] 추가 증분이 남아 있는 단계에서는 롤백을 보류하고 있는가?
- [ ] 마지막 단계의 최종 prepare 종료 코드, 로그와 체크포인트 상태를 함께 확인했는가?
- [ ] 준비 서버의 메모리·디스크 공간·권한·키 접근을 확인했는가?
- [ ] 빈 별도 datadir에 복원하고, 원본과 격리된 서버에서 실제 기동했는가?
- [ ] 미커밋 변경 제외와 정상 커밋 보존을 업무 데이터 기준으로 검증했는가?
- [ ] 전송부터 애플리케이션 전환까지의 복구 시간을 측정했는가?
- [ ] 필요한 복구 시점이 백업 경계를 넘어간다면 PITR 재료와 절차를 별도로 검증했는가?

## 9. 정리

XtraBackup prepare의 핵심은 단순한 파일 형식 변환이 아니라, **redo로 페이지 상태를 복구하고 최종 경계에서 미커밋 트랜잭션을 정리하는 것**이다. 증분 체인에서는 이 두 작업의 시점을 분리해야 나중에 커밋되는 트랜잭션을 보존할 수 있다.

실험에서는 전체 백업 때 열린 트랜잭션의 후속 커밋을 보존하고, 마지막 증분에도 미커밋으로 남은 변경만 제거한 뒤 전체 행 일치를 확인했다. 다음 복구 주제에서는 이 준비된 물리 백업의 경계에 binlog를 연결하여, 원하는 시점까지 어떤 트랜잭션을 적용할지 다루게 된다.

## 참고 문서

- [Percona: 전체 백업 prepare](https://docs.percona.com/percona-xtrabackup/8.0/prepare-full-backup.html)
- [Percona: 증분 백업 prepare와 롤백 보류](https://docs.percona.com/percona-xtrabackup/8.0/prepare-incremental-backup.html)
- [Percona: XtraBackup 8.0 지원 버전](https://docs.percona.com/percona-xtrabackup/8.0/supported-versions.html)
- [Percona: XtraBackup 명령 옵션](https://docs.percona.com/percona-xtrabackup/8.0/xtrabackup-option-reference.html)
- [AWS: Aurora 백업과 복원 개요](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Managing.Backups.html)
- [AWS: 외부 MySQL 백업을 S3에서 Aurora로 이관](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Migrating.ExtMySQL.S3.html)
