mysqlbinlog 기본 사용법: 이벤트 확인, 범위 추출, 안전한 재적용
mysqlbinlog로 binary log 이벤트를 해석하고 시간·위치 범위를 추출한 뒤 복구 대상에 안전하게 재적용하는 절차를 정리한다.
mysqlbinlog는 MySQL binary log를 사람이 읽을 수 있는 텍스트로 변환하고, 선택한 이벤트를 mysql client가 다시 실행할 수 있는 형태로 출력하는 도구다. 장애 분석에서는 “어떤 트랜잭션이 무엇을 바꾸었는가”를 확인하는 데 쓰이고, Point-in-Time Recovery(PITR)에서는 base backup 이후 목표 시점까지 변경 이력을 재생하는 핵심 도구가 된다.
그러나 binary log는 일반 SQL 감사 로그가 아니다. ROW 형식에서는 원래 SQL이 아니라 행의 전후 이미지가 기록되며, 시간이나 position을 잘못 자르면 트랜잭션 경계를 잃을 수 있다. 또한 --base64-output=DECODE-ROWS로 보기 좋게 해석한 출력은 재적용용 원본과 목적이 다르다. 따라서 운영 절차는 확인, 범위 확정, 추출, 검토, 격리된 복구 대상 적용, 결과 검증의 순서를 지켜야 한다.
1. mysqlbinlog의 세 가지 역할
mysqlbinlog 작업은 목적에 따라 다음 세 단계로 나누는 편이 안전하다.
- 이벤트 확인: 파일과 이벤트 구조, 시간, position, GTID, 변경 행을 읽는다.
- 범위 추출: 시간 또는 position으로 필요한 트랜잭션 범위를 별도 파일에 저장한다.
- 재적용: 검토가 끝난 실행 가능 출력을 복구용 MySQL 인스턴스에 입력한다.
flowchart LR
A[base backup 복원] --> B[binary log 목록 확보]
B --> C[mysqlbinlog로 이벤트 확인]
C --> D{복구 경계 확정}
D -->|시간 범위| E[start-datetime / stop-datetime]
D -->|정확한 위치| F[start-position / stop-position]
E --> G[실행 가능 파일로 추출]
F --> G
G --> H[내용·트랜잭션 경계 검토]
H --> I[격리된 복구 대상에 적용]
I --> J[행·업무 규칙·GTID 검증]
J --> K{목표 시점이 맞는가}
K -->|아니오| C
K -->|예| L[서비스 전환 판단]
분석용 명령과 복구용 명령을 분리하는 이유는 간단하다. 사람이 읽기 쉬운 출력이 반드시 재실행 가능한 출력은 아니며, 빠르게 만든 시간 조건이 정확한 복구 경계라는 보장도 없기 때문이다.
2. 작업 전에 고정해야 할 정보
binary log 파일을 열기 전에 다음 정보를 기록한다.
- MySQL Server와
mysqlbinlogutility의 정확한 버전 log_bin,binlog_format,binlog_row_image,gtid_mode- source server의
system_time_zone, global·sessiontime_zone - base backup이 끝난 binary log file/position 또는 GTID 집합
- 복구에서 제외해야 할 사고 트랜잭션의 시간, position, GTID
- 파일이 암호화되었는지와 로컬 파일 접근 가능 여부
- 모든 binary log 파일이 끊김 없이 존재하는지
현재 서버의 핵심 설정은 다음처럼 확인할 수 있다.
SELECT VERSION() AS mysql_version;
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM performance_schema.global_variables
WHERE VARIABLE_NAME IN (
'log_bin',
'binlog_format',
'binlog_row_image',
'gtid_mode',
'system_time_zone',
'time_zone'
)
ORDER BY VARIABLE_NAME;
실행 결과(MySQL 8.0.x):
mysql> SELECT VERSION() AS mysql_version;
+---------------+
| mysql_version |
+---------------+
| 8.0.46 |
+---------------+
1 row in set (0.00 sec)
mysql> SELECT VARIABLE_NAME, VARIABLE_VALUE
-> FROM performance_schema.global_variables
-> WHERE VARIABLE_NAME IN (
-> 'log_bin',
-> 'binlog_format',
-> 'binlog_row_image',
-> 'gtid_mode',
-> 'system_time_zone',
-> 'time_zone'
-> )
-> ORDER BY VARIABLE_NAME;
+------------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+------------------+----------------+
| binlog_format | ROW |
| binlog_row_image | FULL |
| gtid_mode | OFF |
| log_bin | OFF |
| system_time_zone | UTC |
| time_zone | SYSTEM |
+------------------+----------------+
6 rows in set (0.00 sec)
log_bin=OFF인 서버에서는 새 binary log가 생성되지 않는다. binlog_format=ROW이면 데이터 변경은 행 이벤트로 확인하고, binlog_row_image=MINIMAL이면 UPDATE의 before/after image에 모든 열이 나타나지 않을 수 있다. GTID가 활성화된 환경에서는 file/position뿐 아니라 대상 인스턴스의 gtid_executed와 복원 백업의 GTID 시점을 함께 관리해야 한다.
utility 버전도 별도로 확인한다.
mysqlbinlog --version
가능하면 binary log를 생성한 서버와 같거나 더 최신인 동일 계열 utility를 사용한다. 특히 transaction payload compression처럼 새 이벤트 형식이 사용되면 오래된 mysqlbinlog가 파일을 해석하지 못할 수 있다.
3. binary log 이벤트 읽기
3.1 기본 출력은 실행 가능 형태를 보존한다
로컬 binary log 파일을 텍스트로 변환하는 기본 형태는 다음과 같다.
mysqlbinlog mysql-bin.000123 > mysql-bin.000123.sql
기본 출력에는 세션 상태를 재구성하는 SET 문, 트랜잭션 경계, DDL, 그리고 ROW 이벤트를 재실행하기 위한 BINLOG 문이 포함될 수 있다. 이 출력은 사람이 읽기에는 불편하지만 재적용 가능성을 보존한다.
처음부터 pipe로 운영 대상에 흘려보내지 말고 파일로 저장한 뒤 종료 코드와 내용을 확인한다.
set -o pipefail
mysqlbinlog mysql-bin.000123 > recovery-candidate.sql
출력 파일에는 원문 데이터와 스키마명이 들어갈 수 있다. 일반 임시 디렉터리에 방치하지 말고 접근 권한, 저장 위치, 보존 기간을 백업 자료와 같은 수준으로 관리한다.
3.2 ROW 이벤트를 사람이 읽는 형태로 해석한다
ROW 형식의 행 변경을 분석할 때는 다음 조합이 유용하다.
mysqlbinlog \
--base64-output=DECODE-ROWS \
--verbose \
--verbose \
mysql-bin.000123 > mysql-bin.000123.decoded.txt
-v 또는 --verbose는 row event를 ### INSERT, ### UPDATE, ### DELETE 형태의 주석 기반 pseudo-SQL로 복원한다. -vv는 가능한 경우 열 타입과 메타데이터를 더 표시한다. --base64-output=DECODE-ROWS는 분석을 위해 BINLOG 문을 억제하므로 이 출력 파일을 재적용 입력으로 사용하면 안 된다. 재적용 파일은 기본 base64 출력을 유지한 별도 명령으로 생성한다.
MySQL 8.0.46의 축소 검증 환경에서 하나의 송금 트랜잭션을 해석한 결과는 다음과 같았다. 아래는 핵심 이벤트만 발췌한 실제 출력이다.
# at 157
#260905 0:01:55 server id 118 end_log_pos 236 ... Anonymous_GTID ...
# at 236
#260905 0:01:55 server id 118 end_log_pos 332 ... Query ...
BEGIN
# at 332
#260905 0:01:55 server id 118 end_log_pos 410 ... Table_map: `mysqlbinlog_note`.`account_balance`
# at 410
#260905 0:01:55 server id 118 end_log_pos 484 ... Update_rows ...
### UPDATE `mysqlbinlog_note`.`account_balance`
### WHERE
### @1=101
### @2=1000.00
### SET
### @1=101
### @2=875.00
# at 562
#260905 0:01:55 server id 118 end_log_pos 636 ... Update_rows ...
### UPDATE `mysqlbinlog_note`.`account_balance`
### WHERE
### @1=102
### @2=500.00
### SET
### @1=102
### @2=625.00
# at 636
#260905 0:01:55 server id 118 end_log_pos 667 ... Xid = 14
COMMIT/*!*/;
이 출력에서 읽어야 할 핵심은 다음과 같다.
| 항목 | 의미 | 운영 해석 |
|---|---|---|
# at 157 |
이벤트가 시작하는 file-local position | position 범위 후보를 잡는 기준 |
end_log_pos 236 |
해당 이벤트 다음 위치 | 다음 이벤트 경계와 범위 종료 확인 |
GTID 또는 Anonymous_GTID |
트랜잭션 식별 정보 | GTID 적용·중복 여부 판단 |
BEGIN |
트랜잭션 시작 | 중간 row event부터 자르면 안 됨 |
Table_map |
table id와 실제 schema/table 연결 | 뒤따르는 row event 해석에 필요 |
Update_rows |
행 단위 UPDATE 이미지 | 원래 UPDATE 문 자체는 아님 |
Xid와 COMMIT |
트랜잭션 commit | 완전한 재생 범위의 끝 |
@1, @2 같은 표시는 당시 table definition의 열 순서다. 열 이름은 binary log row image에 직접 저장되는 일반 SQL 결과가 아니므로, 사고 시점의 DDL과 현재 DDL이 다르면 해석을 잘못할 수 있다. 분석에는 해당 시점의 schema snapshot도 필요하다.
4. 시간 범위로 추출하기
사고 시각을 대략 알고 있을 때는 먼저 넓은 시간 범위로 후보를 만든다.
TZ=Asia/Seoul mysqlbinlog \
--start-datetime='2026-09-05 08:50:00' \
--stop-datetime='2026-09-05 09:10:00' \
mysql-bin.000123 mysql-bin.000124 \
> recovery-window.sql
시간 기반 추출은 탐색의 출발점으로는 편리하지만 최종 경계로 곧바로 신뢰하면 안 된다.
mysqlbinlog를 실행하는 호스트의 local time zone과 source server의 시간대를 명시적으로 맞춘다.- UTC, KST, daylight saving time이 섞인 환경에서는 사건 시각을 UTC로도 함께 기록한다.
- 두 파일에 범위가 걸치면 필요한 파일을 발생 순서대로 한 번의 명령에 나열한다.
- 추출 후
BEGIN부터COMMIT까지 트랜잭션이 완전한지 확인한다. - 같은 초에 정상 트랜잭션과 사고 트랜잭션이 함께 commit될 수 있으므로 초 단위 시간만으로 최종 제외점을 결정하지 않는다.
분석할 때는 같은 시간 조건에 DECODE-ROWS를 적용한 별도 파일을 만든다.
TZ=Asia/Seoul mysqlbinlog \
--start-datetime='2026-09-05 08:50:00' \
--stop-datetime='2026-09-05 09:10:00' \
--base64-output=DECODE-ROWS -vv \
mysql-bin.000123 mysql-bin.000124 \
> recovery-window.decoded.txt
recovery-window.sql은 실행 가능 후보이고, recovery-window.decoded.txt는 사람의 분석용이다. 파일명을 명확히 분리하면 decoded 출력을 실수로 적용하는 사고를 줄일 수 있다.
5. position 범위로 정확히 자르기
시간 범위에서 목표 트랜잭션을 찾은 뒤에는 position으로 경계를 좁힌다. position은 binary log 파일마다 다시 시작하는 파일 내부 위치이므로 파일명과 한 쌍으로 기록해야 한다.
앞의 검증 로그에서 완전한 트랜잭션은 Anonymous_GTID가 시작하는 position 157에서 시작해 Xid가 끝나는 end_log_pos 667까지였다. 이를 실행 가능 형태로 추출한 명령은 다음과 같다.
mysqlbinlog \
--start-position=157 \
--stop-position=667 \
mysql-bin.000004 \
> recovery-transaction.sql
범위 숫자를 정할 때는 다음 원칙을 지킨다.
Update_rows한 건의 시작점이 아니라GTID또는Anonymous_GTID를 포함한 트랜잭션 시작점을 선택한다.- 마지막 row event에서 멈추지 말고
Xid/COMMIT까지 포함한다. Table_map이벤트가 필요한 row event보다 앞에 있는지 확인한다.- position은 다른 binary log 파일에 그대로 재사용하지 않는다.
- 추출 결과를 다시
mysqlbinlog분석 출력 또는 텍스트 검토로 확인한다.
여러 파일을 연속 재생해야 하면 발생 순서대로 한 번의 mysqlbinlog 호출에 나열하는 편이 안전하다.
mysqlbinlog \
mysql-bin.000121 \
mysql-bin.000122 \
mysql-bin.000123 \
> recovery-chain.sql
파일마다 따로 변환하고 각각 별도 mysql 연결로 실행하면 세션 상태나 temporary table처럼 파일 경계를 넘어 이어지는 문맥을 잃을 수 있다. binary log index 순서, 파일 누락 여부, 각 파일의 rotate 연결을 먼저 확인한다.
6. 재적용은 복구 대상에서 검증한 뒤 수행한다
6.1 권장 절차
재적용 대상은 원본 운영 서버가 아니라 base backup을 복원한 격리 인스턴스여야 한다. 최소 절차는 다음과 같다.
- base backup을 별도 인스턴스에 복원한다.
- backup metadata의 file/position 또는 GTID 시점을 확인한다.
- 이후 binary log를 시간 범위로 넓게 분석한다.
- 트랜잭션 시작과 commit 경계를 position 또는 GTID로 확정한다.
- 실행 가능 출력을 별도 파일로 추출한다.
- decoded 분석 파일과 실행 가능 파일의 범위를 대조한다.
- 복구 대상에 적용하고 첫 오류에서 중단한다.
- row count, 금액 합계, 업무 불변식, 애플리케이션 조회를 검증한다.
- 목표 시점과 다르면 복구 인스턴스를 다시 만들고 경계를 조정한다.
검토가 끝난 파일은 login path를 사용해 적용할 수 있다.
mysql --login-path=recovery_target < recovery-chain.sql
--force로 오류를 건너뛰지 않는다. 중간 오류 후 계속 적용하면 “일부만 복구된 상태”가 만들어져 원인과 재시작 지점을 더 판단하기 어려워진다. shell pipeline을 사용할 때도 pipefail과 양쪽 명령의 종료 상태를 확인한다.
set -o pipefail
mysqlbinlog mysql-bin.000121 mysql-bin.000122 \
| mysql --login-path=recovery_target
직접 pipe는 이미 검증한 반복 실행 절차에만 사용한다. 최초 복구에서는 파일로 남겨 범위, checksum, 승인 기록을 보존하는 편이 좋다.
6.2 schema를 바꿔 축소 검증하는 방법
--rewrite-db='원본->대상'은 row event와 USE 대상 schema를 복구용 schema로 바꿔 제한된 시험을 수행할 때 사용할 수 있다.
mysqlbinlog \
--start-position=157 \
--stop-position=667 \
--rewrite-db='mysqlbinlog_note->mysqlbinlog_recovery' \
mysql-bin.000004 \
| mysql --login-path=recovery_target
MySQL 8.0.46에서 원본과 동일한 table definition, 적용 전 잔액 1000.00과 500.00을 준비한 뒤 이 범위를 실행한 결과는 다음과 같았다.
mysql> SELECT account_id, balance
-> FROM mysqlbinlog_recovery.account_balance
-> ORDER BY account_id;
+------------+---------+
| account_id | balance |
+------------+---------+
| 101 | 875.00 |
| 102 | 625.00 |
+------------+---------+
2 rows in set (0.00 sec)
이 검증은 선택한 범위가 두 UPDATE와 COMMIT을 함께 재생했다는 사실을 보여준다. --rewrite-db가 모든 운영 복구를 안전하게 만드는 것은 아니다. cross-schema statement, stored program, fully qualified object name, DDL 의존성, 권한, trigger를 포함한 로그는 별도 검토가 필요하다.
7. GTID 환경에서의 재적용 판단
GTID가 활성화된 binary log에는 SET @@SESSION.GTID_NEXT가 포함될 수 있다. 복원 대상이 해당 GTID를 이미 실행한 것으로 기록하고 있으면 중복 적용이 건너뛰어지거나 충돌할 수 있고, 반대로 GTID 문맥을 무시하면 원본 복제 이력과 다른 복구 서버가 만들어질 수 있다.
따라서 다음을 먼저 결정한다.
- 원본을 대체할 PITR 인스턴스: base backup의
gtid_executed이후 필요한 원본 GTID를 연속 적용하는 방식이 일반적이다. - 분석용 sandbox: 원본 GTID를 보존할 필요가 있는지, 독립된 새 이력으로 실행할지 결정한다.
- 일부 트랜잭션 제외 복구: 제외한 GTID를 대상에서 어떻게 기록할지와 이후 replica 연결 영향을 설계한다.
--skip-gtids는 출력에서 원본 GTID 관련 문장을 생략할 수 있지만 단순한 오류 회피 옵션이 아니다. 이를 사용하면 대상의 GTID 이력이 원본과 달라질 수 있으므로 향후 replication topology와 전환 절차까지 포함해 결정한다. GTID 상태를 이해하지 못한 채 RESET 계열 명령으로 이력을 지우는 방식도 피한다.
8. 원격 서버에서 읽기와 암호화된 binlog
로컬 파일을 읽을 수 없거나 binary log encryption이 활성화된 경우에는 source server가 이벤트를 해독해 전송하도록 원격 읽기를 사용한다.
mysqlbinlog \
--read-from-remote-server \
--host=db.example.com \
--user=binlog_reader \
--ssl-mode=VERIFY_IDENTITY \
--ssl-ca=/secure/path/ca.pem \
mysql-bin.000123 \
> mysql-bin.000123.sql
계정에는 remote binary log stream을 읽는 데 필요한 최소 replication 권한만 부여하고, 비밀번호를 명령행 인자로 남기지 않는다. 운영에서는 mysql_config_editor의 login path, 보호된 option file, 조직의 secret 주입 방식을 사용한다. TLS 인증서 검증도 생략하지 않는다.
원격 binary log를 원형으로 보관하려면 --raw를 사용할 수 있다.
mysqlbinlog \
--read-from-remote-server \
--raw \
--host=db.example.com \
--user=binlog_archiver \
mysql-bin.000123
--stop-never를 함께 쓰면 연결을 유지하며 새 이벤트를 계속 받을 수 있지만, 이것만으로 완전한 백업 체계가 되지는 않는다. 재연결, 파일 회전, 보존 만료, 중복 수집, 저장 공간, checksum, 접근 통제, 복구 리허설을 별도 운영해야 한다.
9. 필터 옵션에서 자주 발생하는 오류
9.1 --database를 단순 schema 필터로 믿는 경우
--database의 동작은 logging format에 따라 다르다. ROW 형식에서는 해당 schema의 table을 변경하는 row event 중심으로 필터링하지만, STATEMENT 형식에서는 USE로 선택된 default database가 판단에 영향을 준다. cross-database statement나 MIXED 형식이 포함되면 예상하지 못한 이벤트가 빠질 수 있다.
PITR의 첫 추출에서는 전체 연속 구간을 보존하고, schema별 분리가 꼭 필요하면 logging format과 모든 cross-schema 의존성을 검토한 뒤 sandbox에서 결과를 검증한다.
9.2 decoded 출력을 재적용하는 경우
DECODE-ROWS -vv가 보여주는 ### UPDATE는 분석용 주석이다. 원래 predicate와 실행 계획을 복원한 실제 SQL이 아니며, BINLOG payload도 억제된다. decoded 파일은 읽기용, 기본 출력 파일은 적용용으로 분리한다.
9.3 임의의 row event에서 시작하는 경우
Table_map, session state, BEGIN, GTID를 제외한 채 Update_rows부터 자르면 독립적으로 해석하거나 적용할 수 없는 조각이 된다. 트랜잭션 단위로 시작과 끝을 잡는다.
9.4 시간 범위를 곧바로 목표 시점으로 믿는 경우
같은 초에 여러 트랜잭션이 commit될 수 있고 실행 호스트와 source의 시간대가 다를 수 있다. 시간은 후보 탐색에 쓰고 최종 범위는 position, GTID, Xid, 업무 데이터 검증을 함께 사용한다.
9.5 재생을 idempotent하다고 가정하는 경우
INSERT, UPDATE, DELETE, DDL은 일반적으로 임의 재실행에 안전하지 않다. 같은 구간을 두 번 적용하면 duplicate key, 잔액 중복 변경, 이미 존재하는 object 오류가 발생할 수 있다. 매 시도는 검증된 base backup에서 새로 만든 복구 인스턴스에 수행하는 것이 가장 명확하다.
9.6 오류를 무시하고 계속 적용하는 경우
첫 오류는 schema 불일치, 누락된 선행 이벤트, 잘못된 시작점, 권한 부족을 알려주는 신호다. --force로 계속 진행하면 뒤 이벤트까지 연쇄적으로 실패하거나 부분 적용될 수 있다. 오류 시 중단하고 복구 대상을 초기화한 뒤 원인을 수정해 처음부터 재실행한다.
10. Aurora MySQL에서의 해석
Aurora MySQL에서는 DB instance의 data directory에 접근해 로컬 binary log 파일을 직접 여는 방식으로 운영하지 않는다. 목적에 따라 경로를 구분해야 한다.
- 클러스터 시점 복구: Aurora의 continuous backup과 Point-in-Time Restore를 우선 사용한다.
- 외부 replica·CDC·감사용 stream: binary logging과 보존 시간을 엔진 버전 및 cluster parameter에 맞게 구성하고 원격 protocol로 소비한다.
- 사고 트랜잭션 분석: 관리형 로그, 감사 로그, 애플리케이션 기록, 필요한 경우 원격 binary log stream을 함께 사용한다.
- 복구 검증: 새 Aurora cluster 또는 격리된 MySQL 환경에 복원해 결과를 확인한 뒤 전환한다.
Aurora의 관리형 PITR과 외부 소비자용 binary log retention은 서로 다른 기능이다. 관리형 복원이 가능하다는 이유로 CDC consumer가 필요한 binlog가 남아 있다고 가정해서는 안 되며, 반대로 외부 binlog를 보관한다고 Aurora storage snapshot을 대체할 수도 없다.
11. 표준 복구 runbook
단계 1: 변경 동결과 증거 보존
- 추가 purge와 파일 회전을 통제한다.
- 원본 binary log, index, backup metadata를 읽기 전용 위치에 복사한다.
- 파일 크기와 checksum을 기록한다.
- 사고 시각을 애플리케이션 시간, DB 시간, UTC로 각각 기록한다.
단계 2: base backup 복원
- 원본과 분리된 네트워크·계정으로 복구 인스턴스를 만든다.
- 백업 완료 file/position 또는 GTID를 확인한다.
- schema, character set, time zone, SQL mode, plugin 의존성을 맞춘다.
단계 3: 후보 범위 탐색
- 시간 범위로 decoded 분석 파일을 만든다.
- DDL, GTID,
Table_map, row event,Xid를 따라 사고 트랜잭션을 찾는다. - 정상 트랜잭션과 사고 트랜잭션의 경계를 position으로 기록한다.
단계 4: 실행 파일 생성
- 기본 base64 출력을 유지해 실행 가능 파일을 만든다.
- 여러 파일은 index 순서대로 한 번의 명령에 넣는다.
- 추출 파일의 시작이 완전한 트랜잭션 경계인지 확인한다.
- 제외 구간 뒤를 이어 붙일 경우 앞뒤 양쪽의 transaction/GTID 문맥을 검증한다.
단계 5: 적용과 검증
- 복구 대상에 적용하고 첫 오류에서 중단한다.
- 적용 전후 row count와 핵심 합계를 기록한다.
- 외래 키, 잔액 합계, 재고 음수 여부 같은 업무 불변식을 검사한다.
- 애플리케이션 읽기 smoke test와 주요 report를 실행한다.
- 목표 시점이 아니면 같은 인스턴스를 임의 수정하지 말고 base backup부터 재구성한다.
단계 6: 전환과 사후 조치
- 복구 시점 이후 유실될 정상 변경을 목록화하고 재입력 계획을 만든다.
- DNS, endpoint, replica, CDC, backup job의 전환 순서를 정한다.
- 전환 직후 새 base backup을 생성한다.
- 사용한 정확한 명령, 파일, position, GTID, checksum, 검증 결과를 보관한다.
12. DBA 점검표
- binary log를 생성한 서버와 호환되는
mysqlbinlog -
log_bin -
DECODE-ROWS -vv - position을 파일명과 함께 기록하고
BEGIN부터COMMIT - 여러 파일을 올바른 순서로 한 번의
mysqlbinlog -
--database -
--force
맺음말
mysqlbinlog의 기본 사용법은 명령 옵션을 외우는 일이 아니라 binary log의 파일, 이벤트, 트랜잭션, GTID 경계를 보존하는 일이다. DECODE-ROWS -vv로 변경 내용을 읽고, 시간 범위로 후보를 찾은 뒤 position이나 GTID로 트랜잭션 경계를 확정해야 한다. 재적용은 기본 실행 가능 출력을 사용하되, 항상 base backup에서 만든 격리된 복구 대상에 먼저 적용하고 업무 데이터까지 검증한다.
다음 단계에서는 base backup과 binary log를 연결해 특정 사고 트랜잭션 직전까지 복구하고, 이후 정상 트랜잭션만 선별 재생하는 PITR 절차를 더 구체적으로 다룰 수 있다.