Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions docs/decisions/rpo-rto-targets.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# RPO·RTO 목표 — «얼마나 잃어도 되고, 얼마 안에 돌아와야 하나» 를 정하는 분기점

작성일: 2026-11-07 · 갱신: 2026-11-08 (§8-1 읽기 : 쓰기 비율 가정 추가 · §6-2 측정 둘 — 재생 시간·호스트 상실 RPO · 측정 셋 — 새 서버 준비·반출 업로드·리플리카 승격)
상태: 🟡 **방향 확정 · 숫자 미정.** 구성 2(백업 + binlog 서버 밖 반출) 채택, 리플리카 보류, 반동기 미채택
상태: 🟡 **방향 확정 · 목표 RTO 확정(11-08, §6-3) · 나머지 숫자 미정.** 구성 2(백업 + binlog 서버 밖 반출) 채택, 리플리카 보류, 반동기 미채택
(2026-11-07 사용자 confirm). **반출 주기·백업 주기·보존 기간 숫자는 아직 없다** — 추천안이 숫자를 정하지
않았고, 근거 없이 채우지 않는다(§6 Q4·Q6).
연관: [`./backup-restore-rto-rpo.md`](./backup-restore-rto-rpo.md) (복구 시간 실측) ·
Expand Down Expand Up @@ -143,8 +143,7 @@ Flyway 마이그레이션의 테이블 기준. «재생성» 칸은 코드·문
🟡 **반출 주기 숫자는 미정** — 추천안이 정하지 않았다. 고르는 근거는 «주기를 줄일수록 늘어나는 것»
(업로드 횟수·`FLUSH BINARY LOGS` 빈도·작은 binlog 파일 수) — 11-08 에 쟀다: 가정 피크에서 반출 1번에 업로드
0.48~0.71초·FLUSH 52~56ms, 하루 횟수는 60초 주기 1,440번 · 300초 주기 288번(§6-2). FLUSH 가 쓰기를 막는 시간과 요금은 안 쟀다
- [~] **Q5. 호스트 상실 RTO** → 🟢 **리플리카(3) 보류.** 🟡 목표 숫자는 미정 — 구성 2 의 실제 RTO(백업 붓기 +
**binlog 재생**)를 먼저 재고, 그 값이 받아들일 수 없을 때 3 을 다시 연다
- [x] **Q5. 목표 RTO** → 🟢 **장애 종류별 · 시간대별 목표 확정, 리플리카(3) 보류 유지** (2026-11-08 사용자 confirm, §6-3)
- [~] **Q6. 백업 주기·보관 위치·보존 기간** → 🟢 **위치는 서버 밖**(구성 2 의 정의). 🟡 **주기·보존 기간은 미정** —
운영 호스트가 정해지지 않았다(`31-production-readiness-plan.md:218` 과 같은 이유)
- [x] **반동기(4)** → 🟢 **채택 안 함** (§6-1 근거)
Expand All @@ -159,6 +158,31 @@ Flyway 마이그레이션의 테이블 기준. «재생성» 칸은 코드·문
- **반동기(4) 는 채택 안 함 쪽.** 근거: 쓰기가 무거운 경로(`pose_data` 적재)에 대가가 붙고, 그
데이터의 상당 부분은 원래 버리는 버퍼(E 등급)이며, 리플리카 1대 구성에선 조용히 강등된다

### 6-3. 목표 RTO — ✅ 2026-11-08 사용자 confirm

정하는 방식 (셋 다 추천대로):
- **장애 종류별로** 따로 둔다 — 복구 경로(자동 재기동 · 사람이 새 서버 · 사람이 PITR)가 다르다
- **사람 시간을 넣는다** — 알림이 휴대폰에 온다는 전제. 사용자가 겪는 시간과 맞추려고
- **시간대별로** 나눈다 — 운동이 몰리는 저녁에 운영자도 깨어 있고, 운영자가 못 보는 새벽엔 사용자가 적다.
🔴 «저녁이 붐빈다» 는 상식 가정이다 — 시간대별 사용량 실측은 없다(출시 전). 출시 뒤 사용 기록으로 확인할 것

| 장애 | 시간대 | 목표 | 어디서 나온 숫자 | 지금 맞나 |
|---|---|---|---|---|
| MySQL 프로세스 죽음 | 하루 종일 | **19초** | AI→Spring 결과 전달 재시도 한도(약 19초, `spring_client.py`) — 넘으면 방금 끝난 운동이 `FAILED` | 가정 피크 ✅(재기동 1.9~2.4초) · 최대 쓰기 ❌(33.6~35.1초, redo 약 1.35GB) — [프로세스 재기동 실측](../../loadtest/results/process-restart-rto-2026-11-08/README.md) |
| 호스트 상실 | 저녁 18시~01시 | **약 37분** | 사람 30분(사용자 답) + 구성 2 복구 약 7분(실측 합) | 🟡 7분은 서로 다른 실험의 합 — 처음부터 끝까지 한 번에 해 본 적 없음 |
| 호스트 상실 | 낮 08시~18시 | **약 67분** | 사람 60분(사용자 답) + 약 7분 | 위와 같음 |
| 호스트 상실 | 새벽 01시~08시 | **기상(08시) 뒤 손대기 시작 + 약 7분** — 최악 약 7시간 | 운영자 수면 | 위와 같음 |
| 논리 사고 | — | 🟡 미정 | | |

**리플리카(3) 를 보류로 두는 이유**: 리플리카가 줄이는 건 기술 시간(약 7분 → 승격 약 1.2초 + 앱 전환 수 초~약 2분)뿐이고
사람 시간은 그대로다. 저녁 기준 약 37분 → 약 31~32분(약 14%)인데 대가는 서버 1대 상시 + 복제 감시다.
37분을 줄이려면 리플리카보다 **알림 속도·복구 절차 한 번에 실행**이 먼저다.

목표를 지키려면 남은 일 (목표의 전제):
- 🔴 **장애 알림이 없다** — 사람 30·60분은 알림이 있다는 전제다 (모니터링 점검 #673~680 미완)
- 🔴 **복구 훈련 한 번** — 구성 2 를 처음부터 끝까지 실제로 돌려 7분을 확인(R1)
- 🟡 **최대 쓰기에서 프로세스 재기동 19초 초과** — 재기동 시간이 쌓인 redo 양에 비례한다. 줄일 방법은 미정

### 6-2. 결정 전에 재면 좋은 것

| 무엇 | 왜 | 어디서 |
Expand Down Expand Up @@ -273,3 +297,8 @@ DAU 와 비교해 판단을 닫지 않는다는 원칙과도 어긋난다([[feed
③ [승격 실측](../../loadtest/results/replica-promotion-2026-11-08/README.md): DB 쪽 승격 **밀림 없으면 약 0.25초 · 약 21초 밀리면 약 7.8초**(본판 8, 잃은 트랜잭션 0).
한 박스 동거라 «잃은 0» 은 다른 박스에선 성립하지 않고, 감지·결정·앱 연결 전환 시간은 빠져 있다.
→ Q5 를 다시 열지는 «구성 2 의 약 7분이 목표 RTO 안에 드나» 로 가른다 — 목표 숫자는 아직 없다.
- 2026-11-08: 🟢 **Q5 목표 RTO 확정** (사용자 confirm, §6-3). 장애 종류별·시간대별, 사람 시간 포함(알림 전제).
프로세스 죽음 19초 · 호스트 상실 저녁 약 37분 / 낮 약 67분 / 새벽 기상 뒤 약 7분 · 논리 사고 미정.
리플리카(3) 는 **보류 유지** — 줄이는 게 기술 시간 약 7분뿐이고 사람 시간이 대부분이라서.
근거로 쓴 같은 날 실측 둘: [프로세스 재기동](../../loadtest/results/process-restart-rto-2026-11-08/README.md)(쉼 1.3초 · 가정 피크 1.9~2.4초 · 최대 쓰기 33.6~35.1초, 잃은 0) ·
[페일오버 앱 전환](../../loadtest/results/failover-app-reconnect-2026-11-08/README.md)(앱 재시작 약 106초 · DNS 5~30초, 단 네트워크 끊김에서 요청 약 14개가 약 16분 매달림, 잃은 0).
65 changes: 65 additions & 0 deletions loadtest/results/process-restart-rto-2026-11-08/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# 프로세스 재기동 RTO — mysqld 가 죽은 순간부터 다시 쿼리를 받기까지 (2026-11-08, EC2)

설계 문서: [`../../../docs/decisions/rpo-rto-targets.md`](../../../docs/decisions/rpo-rto-targets.md) §4 첫 줄 · §6-3 (목표 RTO)
무대: **EC2 `m6i.xlarge` 1대** · gp3 200GB · MySQL **8.0.46**(`mysql:8.0`) · `flush=1`·`sync_binlog=1` · binlog ROW ·
버퍼풀 2GB · redo 용량 2GB · RUN_ID `restart-ec2-20261108-060158` · 커밋 `22ce55f4` · 12판(버림 3 + 본판 9)

질문: OOM kill·크래시로 mysqld 만 죽고 디스크는 남았을 때(문서 §4 «프로세스 죽음»), 다시 쓸 수 있기까지 얼마나 걸리나?
그 시간은 죽는 순간 «디스크 반영이 덜 된 변경(redo)» 양에 따라 늘 것으로 예상했다.

## 0. 한 줄

**쉬는 중 1.3초 · 가정 피크(초당 45행) 1.9~2.4초 · 최대 쓰기 33.6~35.1초 — 재기동 시간은 쌓인 redo 양을 따라간다. 잃은 트랜잭션은 0.**
목표 RTO 19초(§6-3)는 가정 피크에선 맞고, 최대 쓰기에선 못 맞춘다.

## 1. 결과 (본판)

| 팔 | 판 | 죽일 때 redo | 더러운 페이지 | **재기동** (`docker start` → 첫 `SELECT 1`) | 죽은 순간부터 | 잃은 트랜잭션 |
|---|---:|---:|---:|---:|---:|---:|
| idle | 5 | 0 | 0 | **1,279ms** | 1,677ms | — |
| idle | 9 | 0 | 0 | **1,349ms** | 1,700ms | — |
| idle | 10 | 0 | 0 | **1,363ms** | 1,782ms | — |
| paced | 6 | 14MB | 961 | **2,446ms** | 2,883ms | 0 |
| paced | 7 | 14MB | 948 | **1,886ms** | 2,351ms | 0 |
| paced | 12 | 14MB | 949 | **2,414ms** | 2,910ms | 0 |
| stress | 4 | 1,334MB | 73,194 | **35,058ms** | 36,156ms | 0 (−2) |
| stress | 8 | 1,348MB | 73,361 | **34,356ms** | 35,481ms | 0 (−2) |
| stress | 11 | 1,355MB | 73,626 | **33,577ms** | 34,716ms | 0 (−4) |

(버림판: idle 1,322ms · paced 2,393ms · stress 31,990ms — 본판과 같은 범위)

- **redo 14MB → 약 2초, 약 1.35GB → 약 34초.** 쉬는 중의 약 1.3초는 redo 와 무관한 고정 비용(컨테이너·서버 기동 + rig 의 `docker exec` 약 41ms)이다
- **잃은 트랜잭션 0.** 음수(−2·−4)는 «클라이언트가 성공 응답을 받은 것보다 DB 에 더 있다» 는 뜻이다 — 서버는 커밋했는데 응답이 돌아오기 전에 죽은 요청.
연결 수(4) 를 넘지 않는다. `flush=1`·`sync_binlog=1` 의 약속 그대로다
- stress 는 체크포인트가 쓰기를 못 따라가 redo 가 용량(2GB)의 약 3분의 2 까지 쌓인 상태였다

## 2. 목표 RTO 와 나란히 (§6-3)

| 상황 | 재기동 | 목표 19초 |
|---|---|---|
| 쉼 | 1.3초 | ✅ |
| 가정 피크 (초당 45행) | 1.9~2.4초 | ✅ |
| 최대 쓰기 (4연결 240초) | 33.6~35.1초 | ❌ |

19초는 AI→Spring 결과 전달 재시도 한도(약 19초)에서 왔다 — 넘으면 방금 끝난 운동이 `FAILED` 가 된다.
최대 쓰기에서 못 맞추는 걸 어떻게 할지(redo 용량·체크포인트 설정 등)는 **정하지 않았다** — 재기동 시간을 줄이는 값은 평소 쓰기 비용과 맞바꾸는 것이라 따로 재야 한다.

## 3. 조건 — 인용할 때 떼면 안 되는 것

1. **감시·사람 시간 0.** 죽이고 바로 `docker start` 했다. 운영의 `restart: unless-stopped` 가 다시 띄우기까지의 시간은 안 쟀다
2. «죽음» 은 `docker kill`(SIGKILL) — 컨테이너만 죽고 호스트·볼륨은 남는다. 호스트 상실은 [다른 실험](../hostloss-rpo-2026-11-07/README.md)
3. paced 는 문서 §8-1 **가정** 피크(측정 아님), stress 는 4개 연결이 240초간 최대 속도 — 상한 확인용이지 운영 값이 아니다
4. 🟡 **redo 적용에 걸린 시간만 따로는 못 뽑았다.** 서버 로그에서 «복구 시작 · redo 적용 끝» 시각을 뽑으려 했는데(`recov_start_ms`·`redo_done_ms`)
전부 비었다 — 로그 문구 매칭이 8.0.46 출력과 안 맞은 것으로 보인다(확인 안 함). 그래서 «34초 중 redo 적용이 몇 초» 는 말할 수 없다
5. 버퍼풀 2GB · redo 2GB 는 rig 의 값이다. 운영 설정에선 쌓이는 redo 상한이 달라 stress 의 숫자가 달라진다
6. 🟡 `round.log` 의 `bootstrap.sh: line 281: ... command not found` 는 이 rig 이 쓰지 않는 단계의 오류다 — 측정과 무관

## 4. 재현

```bash
bash launch.sh <커밋 SHA> # EC2 1대. 결과는 S3 의 RUN_ID 아래
OUT=$PWD/_out PACED_SECS=30 STRESS_SECS=60 bash restart.sh # 로컬 스모크
```

산출물: `ec2/trials.tsv`(판 1줄) · `ec2/CONDITIONS.txt` · `ec2/run.log` · `ec2/box.txt` · `ec2/round.log`.
판별 원본(쓰기 클라이언트 `w_*.tsv`, 판별 서버 로그)은 저장소에 안 넣었다 — S3 `shadowfit/restart-ec2-20261108-060158/out/t*/`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# 프로세스 재기동 실험 조건 (2026-11-08T06:04:43+00:00)
mysql image : mysql:8.0 (mysql@sha256:7dcddc01f13bab2f15cde676d44d01f61fc9f99fe7785e86196dfc07d358ae2b)
server opts : --server-id=1 --log-bin=binlog --binlog-format=ROW --innodb-flush-log-at-trx-commit=1 --sync-binlog=1 --innodb-buffer-pool-size=2G --innodb-redo-log-capacity=2G
trials : idle paced stress stress idle paced paced stress idle idle stress paced (앞 3 판 버림)
idle 30s · paced 45행/초(문서 §8-1 가정) 120s · stress 4연결 240s
recov_*/conn_ms 는 docker start 기준, 서버 로그 시각(초 단위 정밀도는 로그 형식에 따름)
7 changes: 7 additions & 0 deletions loadtest/results/process-restart-rto-2026-11-08/ec2/box.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
instance_type=m6i.xlarge
4
total used free shared buff/cache available
Mem: 15 0 10 0 4 14
Swap: 0 0 0
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p1 200G 6.8G 194G 4% /
201 changes: 201 additions & 0 deletions loadtest/results/process-restart-rto-2026-11-08/ec2/round.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
== start 2026-11-08T06:02:27+00:00 SHA=22ce55f486bfc80d7ab58558cd87e9ba0ba805c1 RUN_ID=restart-ec2-20261108-060158 CAP_MIN=150

──── root SSH (다른 박스가 이 박스로 붙는 라운드용, #642) ────
ec2-user 의 authorized_keys 를 root 로 복사(강제명령 줄 제거), PermitRootLogin prohibit-password

──── 패키지 ────
buildx 0.12.2 → 0.19.3 으로 올린다 (compose build 는 0.17+ 를 요구한다)

──── 저장소 — https://github.com/Shadowfit/init.git @ 22ce55f486bfc80d7ab58558cd87e9ba0ba805c1 ────
커밋: 22ce55f4

──── .env ────
bootstrap.sh: line 281: compose: command not found
bootstrap.sh: line 281: shadowfit-ai: command not found
bootstrap.sh: line 281: INTERNAL_API_TOKEN:?: command not found
bootstrap.sh: line 281: MYSQL_EXPORTER_PASSWORD: command not found
bootstrap.sh: line 281: :?: command not found
bootstrap.sh: line 281: shadowfit-ai: command not found
bootstrap.sh: line 281: INTERNAL_API_TOKEN: command not found
bootstrap.sh: line 281: unused-in-this-role: command not found
MYSQL_ROOT_PASSWORD 를 rig 기본값과 맞췄다 (+ 해석만 되면 되는 변수들)
compose 해석 확인 ✅ (mysql 만 띄워도 파일 전체가 해석된다)

──── MySQL 컨테이너 ────
time="2026-11-08T06:03:24Z" level=warning msg="/root/init/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion"
Image mysql:8.0 Pulling
edf85873f64e Pulling fs layer 0B
6ef6c7b50a93 Pulling fs layer 0B
e3e5d1ac74c1 Pulling fs layer 0B
0d74d296605b Pulling fs layer 0B
297d04cfe470 Pulling fs layer 0B
4c8a3e0d4e4b Pulling fs layer 0B
a63160a5eda1 Pulling fs layer 0B
7534d1db9f8d Pulling fs layer 0B
49ec2dab01d9 Pulling fs layer 0B
ab24264a27e9 Pulling fs layer 0B
96d30d9fbee8 Pulling fs layer 0B
297d04cfe470 Waiting 0B
4c8a3e0d4e4b Waiting 0B
7534d1db9f8d Waiting 0B
49ec2dab01d9 Waiting 0B
a63160a5eda1 Waiting 0B
ab24264a27e9 Waiting 0B
96d30d9fbee8 Waiting 0B
0d74d296605b Waiting 0B
e3e5d1ac74c1 Downloading 16.38kB
6ef6c7b50a93 Downloading 884B
6ef6c7b50a93 Verifying Checksum 0B
6ef6c7b50a93 Download complete 0B
e3e5d1ac74c1 Download complete 0B
edf85873f64e Downloading 488.4kB
edf85873f64e Verifying Checksum 0B
edf85873f64e Download complete 0B
edf85873f64e Extracting 491.5kB
edf85873f64e Extracting 5.407MB
edf85873f64e Extracting 8.356MB
edf85873f64e Extracting 17.69MB
edf85873f64e Extracting 27.03MB
297d04cfe470 Downloading 2.607kB
297d04cfe470 Verifying Checksum 0B
297d04cfe470 Download complete 0B
0d74d296605b Downloading 64.9kB
0d74d296605b Verifying Checksum 0B
0d74d296605b Download complete 0B
edf85873f64e Extracting 32.93MB
4c8a3e0d4e4b Downloading 335B
4c8a3e0d4e4b Verifying Checksum 0B
4c8a3e0d4e4b Download complete 0B
edf85873f64e Extracting 42.76MB
edf85873f64e Extracting 44.24MB
edf85873f64e Extracting 47.31MB
edf85873f64e Pull complete 0B
6ef6c7b50a93 Extracting 884B
6ef6c7b50a93 Extracting 884B
6ef6c7b50a93 Pull complete 0B
e3e5d1ac74c1 Extracting 32.77kB
e3e5d1ac74c1 Extracting 783.6kB
e3e5d1ac74c1 Extracting 783.6kB
e3e5d1ac74c1 Pull complete 0B
0d74d296605b Extracting 65.54kB
a63160a5eda1 Downloading 502.3kB
7534d1db9f8d Downloading 316B
7534d1db9f8d Verifying Checksum 0B
7534d1db9f8d Download complete 0B
0d74d296605b Extracting 2.884MB
a63160a5eda1 Downloading 42.36MB
49ec2dab01d9 Downloading 536.5kB
a63160a5eda1 Verifying Checksum 0B
a63160a5eda1 Download complete 0B
0d74d296605b Extracting 6.173MB
0d74d296605b Pull complete 0B
297d04cfe470 Extracting 2.607kB
297d04cfe470 Extracting 2.607kB
297d04cfe470 Pull complete 0B
4c8a3e0d4e4b Extracting 335B
4c8a3e0d4e4b Extracting 335B
4c8a3e0d4e4b Pull complete 0B
a63160a5eda1 Extracting 524.3kB
49ec2dab01d9 Downloading 44.08MB
a63160a5eda1 Extracting 7.864MB
49ec2dab01d9 Downloading 88.05MB
a63160a5eda1 Extracting 14.16MB
49ec2dab01d9 Verifying Checksum 0B
49ec2dab01d9 Download complete 0B
a63160a5eda1 Extracting 23.07MB
ab24264a27e9 Downloading 5.327kB
ab24264a27e9 Verifying Checksum 0B
ab24264a27e9 Download complete 0B
a63160a5eda1 Extracting 32.51MB
a63160a5eda1 Extracting 40.37MB
96d30d9fbee8 Downloading 120B
96d30d9fbee8 Download complete 0B
a63160a5eda1 Extracting 48.23MB
a63160a5eda1 Extracting 49.93MB
a63160a5eda1 Pull complete 0B
7534d1db9f8d Extracting 316B
7534d1db9f8d Extracting 316B
7534d1db9f8d Pull complete 0B
49ec2dab01d9 Extracting 557.1kB
49ec2dab01d9 Extracting 9.47MB
49ec2dab01d9 Extracting 17.83MB
49ec2dab01d9 Extracting 22.28MB
49ec2dab01d9 Extracting 28.41MB
49ec2dab01d9 Extracting 31.75MB
49ec2dab01d9 Extracting 32.31MB
49ec2dab01d9 Extracting 32.87MB
49ec2dab01d9 Extracting 33.42MB
49ec2dab01d9 Extracting 33.98MB
49ec2dab01d9 Extracting 34.54MB
49ec2dab01d9 Extracting 35.65MB
49ec2dab01d9 Extracting 36.21MB
49ec2dab01d9 Extracting 37.32MB
49ec2dab01d9 Extracting 37.88MB
49ec2dab01d9 Extracting 38.44MB
49ec2dab01d9 Extracting 38.99MB
49ec2dab01d9 Extracting 39.55MB
49ec2dab01d9 Extracting 40.11MB
49ec2dab01d9 Extracting 41.22MB
49ec2dab01d9 Extracting 42.34MB
49ec2dab01d9 Extracting 42.89MB
49ec2dab01d9 Extracting 43.45MB
49ec2dab01d9 Extracting 44.56MB
49ec2dab01d9 Extracting 45.68MB
49ec2dab01d9 Extracting 46.24MB
49ec2dab01d9 Extracting 47.91MB
49ec2dab01d9 Extracting 49.58MB
49ec2dab01d9 Extracting 52.36MB
49ec2dab01d9 Extracting 60.72MB
49ec2dab01d9 Extracting 69.07MB
49ec2dab01d9 Extracting 77.43MB
49ec2dab01d9 Extracting 86.34MB
49ec2dab01d9 Extracting 95.81MB
49ec2dab01d9 Extracting 106.4MB
49ec2dab01d9 Extracting 117MB
49ec2dab01d9 Extracting 127MB
49ec2dab01d9 Extracting 129.4MB
49ec2dab01d9 Pull complete 0B
ab24264a27e9 Extracting 5.327kB
ab24264a27e9 Extracting 5.327kB
ab24264a27e9 Pull complete 0B
96d30d9fbee8 Extracting 120B
96d30d9fbee8 Extracting 120B
96d30d9fbee8 Pull complete 0B
Image mysql:8.0 Pulled
Network init_shadowfit-net Creating
Volume init_mysql_data Creating
Volume init_mysql_data Creating
Network init_shadowfit-net Creating
Volume init_mysql_data Created
Volume init_mysql_data Created
Network init_shadowfit-net Created
Network init_shadowfit-net Created
Container shadowfit-mysql Creating
Container shadowfit-mysql Created
Container shadowfit-mysql Starting
Container shadowfit-mysql Started
준비 대기... — 떴다 (TCP 인증 질의 연속 2회)

──── percona-toolkit 이미지 ────
docker.io/percona/percona-toolkit:latest

──── xtrabackup 이미지 (P3 백업 · P4 복제) — percona/percona-xtrabackup:8.0 ────
docker.io/percona/percona-xtrabackup:8.0

──── 스키마 — Flyway 마이그레이션 ────
SKIP_FLYWAY=1 — 건너뛴다. 從 R1·R3 은 «측정 대상 부재» 로 찍힌다

──── 준비됨 ────
작업 디렉터리 : /root/init
커밋 : 22ce55f4 (22ce55f486bfc80d7ab58558cd87e9ba0ba805c1)
디스크 여유 : 193G
MySQL : 8.0.46

다음:
cd /root/init
S3_BASE=s3://<버킷>/<프리픽스> nohup bash loadtest/aws/run_all.sh > /root/run_all.log 2>&1 &

⚠️ nohup 없이 & 만 붙이면 SSH 가 끊길 때 같이 죽는다.
shadowfit-mysql
== rig exit 0
== finish: DONE rc=0 (2026-11-08T06:35:42+00:00)
Loading
Loading