운영 서버에서 DB index 적용 작업 진행

- 01~07 작업 문서를 운영 측정값 기준으로 정리 (문서의 DB 비밀번호 삭제)
- app_highest_record 중복 8,795행 점수 기준 정리, 인덱스 5개 + UNIQUE 키 2개 추가
- 02·04 공통 측정 스크립트와 측정 결과, comparison.txt 추가
- 서버 처리 시간 18~292배 단축, 결과 행 수 동일
- 운영 데이터 백업과 권한(비밀번호 해시) 파일은 커밋에서 제외

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 23:30:42 +09:00
parent ded12332d5
commit 03eea2098e
56 changed files with 6993 additions and 0 deletions
@@ -0,0 +1,127 @@
# 06단계: 롤백 계획
> 문제 발생 시 인덱스를 삭제하고, 필요하면 중복 정리 전 상태로 되돌립니다.
>
> ⚠️ 작업용 `jisangs` 계정은 2026-09-15에 삭제했습니다. 이 문서의 `-u jisangs` 명령은 관리자 계정으로 바꿔 실행하세요.
모든 명령은 `result/` 디렉터리에서 실행합니다.
---
## 🚨 긴급 상황 대응
### 1. 진행 중인 ALTER 중단
```bash
mariadb -h chocomae.jinaju.com -u jisangs -p chocomae -e "SHOW PROCESSLIST;" | grep ALTER
# 첫 번째 열(Id)의 값을 넣어 실행
mariadb -h chocomae.jinaju.com -u jisangs -p chocomae -e "KILL QUERY <Id>;"
```
> 온라인 DDL을 중단하면 그 인덱스만 만들어지지 않고 테이블 데이터는 그대로입니다. 내 계정이 실행한 쿼리는 별도 권한 없이 중단할 수 있습니다.
### 2. 인덱스 삭제
```bash
mariadb -h chocomae.jinaju.com -u jisangs -p chocomae << 'EOF'
-- 모든 인덱스 삭제
ALTER TABLE best_record DROP INDEX IF EXISTS idx_maestro_app_dt;
ALTER TABLE best_record DROP INDEX IF EXISTS idx_maestro_player_app_dt;
ALTER TABLE typing_exam_record DROP INDEX IF EXISTS idx_maestro_writing_dt;
ALTER TABLE typing_exam_record DROP INDEX IF EXISTS idx_maestro_player_writing_dt;
ALTER TABLE license_score DROP INDEX IF EXISTS idx_maestro_player_dt;
ALTER TABLE app_highest_record DROP INDEX IF EXISTS uk_maestro_player_app;
ALTER TABLE typing_exam_highest_record DROP INDEX IF EXISTS uk_maestro_player_writing;
EOF
```
> UNIQUE 키 2개는 성능과 무관하므로, 성능 문제로 롤백할 때는 남겨 두어도 됩니다. 남겨 두면 중복이 다시 생기지 않습니다.
---
## 중복 정리 되돌리기 (필요할 때만)
삭제한 행은 같은 조합의 **덜 좋은 기록**이라 보통 되돌릴 필요가 없습니다. 되돌려야 하면 UNIQUE 키를 먼저 삭제한 뒤 03단계 3-0-2의 백업 파일을 실행합니다. (INSERT 권한 — jisangs에 임시 부여됨)
```bash
mariadb -h chocomae.jinaju.com -u jisangs -p chocomae -e "
ALTER TABLE app_highest_record DROP INDEX IF EXISTS uk_maestro_player_app;"
mariadb -h chocomae.jinaju.com -u jisangs -p chocomae < backup_app_highest_dup_rows.sql
mariadb -h chocomae.jinaju.com -u jisangs -p chocomae -e "
SELECT COUNT(*) AS total_rows FROM app_highest_record;"
```
> 백업 파일은 원래 ID 그대로 INSERT하므로 기존 행과 충돌하지 않습니다. 복원 후 `total_rows`는 3-0-3 삭제 전 행 수(그 사이 새로 저장된 기록 제외)와 같아야 합니다.
---
## 전체 백업에서 복원 (최후의 수단)
운영 DB는 AWS RDS가 아니라 **EC2의 Docker MariaDB**입니다. 인덱스 문제는 DROP INDEX로 충분하므로 데이터 손상이 있을 때만 사용하세요. **백업 이후 저장된 게임 기록은 모두 사라집니다.**
### 방법 1: 덤프 파일 복원
```bash
# EC2 서버의 MariaDB 컨테이너 안에서 관리자 계정으로 실행
mariadb -u <관리자> -p chocomae < backup_2026-09-15.sql
```
### 방법 2: EBS 스냅샷 복원
1. AWS 콘솔 → EC2 → 스냅샷에서 작업 전 스냅샷 선택
2. 스냅샷으로 볼륨 생성 (EC2 인스턴스와 같은 가용 영역)
3. MariaDB 컨테이너 중지 → 기존 데이터 볼륨 분리 → 새 볼륨 연결·마운트
4. 컨테이너 시작 후 접속 확인
### 복제 상태 확인 (복제를 사용 중인 경우, 관리자 계정)
```sql
SHOW MASTER STATUS;
SHOW REPLICA STATUS\G
```
### 서비스 정상 확인
- 웹 서비스 접속 테스트
- 타이핑 게임 플레이 테스트 (결과 저장, 최고기록 표시)
- 랭킹 조회 테스트
---
## 문제 원인 분석
| 증상 | 원인 | 대응 |
|---|---|---|
| 인덱스 생성 실패 | 디스크 부족 | DROP INDEX + 디스크 정리 |
| `Duplicate entry ... for key 'uk_...'` | 3-0 이후 새 중복 발생 | 3-0-2·3-0-3 다시 실행 후 `add_indexes.sql` 재실행 (이미 만든 인덱스는 건너뜀) |
| 서비스 느려짐 | 옵티마이저가 새 인덱스를 잘못 선택, 통계 부정확 | `ANALYZE TABLE best_record;` (관리자) → 그래도 느리면 해당 인덱스 DROP |
| 최고기록 화면 값 이상 | 중복 정리 결과 | 백업 파일에서 해당 조합 확인, 필요하면 "중복 정리 되돌리기" |
| 복제 지연·오류 | 복제 서버에서 DDL 적용 중 또는 실패 | `SHOW REPLICA STATUS`로 확인 |
---
## 복구 후 확인
```bash
# 테이블 상태 확인
mariadb -h chocomae.jinaju.com -u jisangs -p chocomae -e "
SHOW INDEXES FROM best_record;
SELECT COUNT(*) FROM best_record;
"
```
성능 확인은 `zsh run_measure.sh after`로 다시 측정해 `baseline_perf.txt`와 비교합니다. 기존 `after_*` 파일을 덮어쓰므로 먼저 다른 폴더로 옮기세요.
---
## 문제 발생 시 연락
- **팀 리더**: [연락처]
- **DBA**: [연락처]
- **운영팀**: [연락처]
---
**롤백은 최후의 수단입니다. 충분한 검토 후 신중하게 진행하세요.** ⚠️