fix: V010 MySQL 미지원 조건부 DDL 제거로 Flyway 마이그레이션 실패 해결 - #136
Conversation
인덱스 생성 시 MySQL 문법 호환성 문제로 인해 V010을 단순화했습니다. - V010: 컬럼 제거 및 테이블 생성만 수행 - V011: 조회 성능 최적화용 인덱스 생성 (별도 마이그레이션으로 분리) 이미 인덱스가 존재하는 경우 MySQL 8.0과의 호환성을 고려하여 V011에서는 CREATE INDEX만 수행하며, 중복 생성 시에는 운영팀 수동 개입이 필요합니다. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MySQL 은 DROP COLUMN IF EXISTS / CREATE INDEX IF NOT EXISTS 를 지원하지 않는다 (MariaDB 전용 확장). 이 구문 때문에 V010 이 운영 DB 에서 실패했고, flyway_schema_history 에 남은 실패 이력이 validate 단계에서 애플리케이션 부팅을 차단해 배포와 롤백이 모두 실패했다. - V010: DROP COLUMN 문 제거. last_activity_read_at 은 ProjectMember 엔티티와 운영 DB 어디에도 없어 애초에 불필요했다. - V011: 삭제. 대상 인덱스는 운영 DB 에 이미 존재하고 FK(project_id -> project.id) 를 떠받치고 있어 제거할 수 없으므로 마이그레이션 대상에서 제외한다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughV010 마이그레이션에서 ChangesV010 마이그레이션 DDL 정리
Estimated code review effort: 1 (Trivial) | ~3 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/resources/db/migration/V010__project_activity_read.sql`:
- Around line 17-19: Update the V010 migration to create the equivalent
composite index on activity_log(project_id, created_at, id), rather than
omitting it based on the operational database assumption. Keep the index aligned
with ActivityLogRepository.findRecentActivitiesByCursor() filtering and ordering
so new databases receive the required index.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3a23fba8-1553-4d1e-80c2-e7b2ca8bf33f
📒 Files selected for processing (1)
src/main/resources/db/migration/V010__project_activity_read.sql
|
|
||
| -- activity_log (project_id, created_at, id) 인덱스는 운영 DB에 이미 존재하며 | ||
| -- FK(project_id -> project.id) 를 떠받치고 있어 제거할 수 없으므로 마이그레이션에 포함하지 않는다. |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
rg -n -C 6 \
'activity_log|project_id|created_at|CREATE[[:space:]]+INDEX|FOREIGN KEY' \
--glob '*.sql' .Repository: SLAT-TO/SLATE-TO-BE
Length of output: 11690
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf 'SQL migration files:\n'
git ls-files 'src/main/resources/db/migration/*.sql' | sort
printf '\nactivity_log references and DDL patterns:\n'
rg -n -C 8 \
'CREATE\s+TABLE\s+(?i:activity_log)|activity_log|INDEX|KEY|\bFOREIGN\s+KEY\b|REFERENCES\s+\(?\s*id' \
--glob '*.sql' src/main/resources/db/migration
printf '\nEntity/controller usage of activity_log indexes/created_at/project_id:\n'
rg -n -C 4 \
'activityLog|ActivityLog|createdAt|created_at|project_id|projectId' \
src/main/java || trueRepository: SLAT-TO/SLATE-TO-BE
Length of output: 50376
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf 'activity_log file candidates:\n'
fd -a 'activity_log|ActivityLog|notification' src/main/resources src/main/java | sed 's#^\./##' | head -200
printf '\nMigrations mentioning activity_log explicitly:\n'
for f in $(git ls-files 'src/main/resources/db/migration/*.sql'); do
if grep -qi 'activity_log' "$f"; then
echo "--- $f"
cat -n "$f"
fi
done
printf '\nRepository/projection files related to ActivityLog:\n'
fd -a 'ActivityLog|activity' src/main/java | sed 's#^\./##' | while read -r f; do
if grep -qiE 'activity_log|ActivityLog|last_activity_at|lastActivityAt|findLatest|created_at|created' "$f"; then
echo "--- $f"
sed -n '1,220p' "$f"
fi
doneRepository: SLAT-TO/SLATE-TO-BE
Length of output: 15866
activity_log의 최신 조회용 복합 인덱스를 마이그레이션에 포함하세요.
V004/V007은 activity_log를 삭제하거나 변경하지 않으며, V009와 V010도 (project_id, created_at, id) 인덱스 생성을 하지 않습니다. ActivityLogRepository.findRecentActivitiesByCursor()가 projectId, createdAt, id로 정렬/필터하므로, 운영 DB 의존성 없이 신규 DB에도 동일한 동등 인덱스를 생성하도록 변경하세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/resources/db/migration/V010__project_activity_read.sql` around lines
17 - 19, Update the V010 migration to create the equivalent composite index on
activity_log(project_id, created_at, id), rather than omitting it based on the
operational database assumption. Keep the index aligned with
ActivityLogRepository.findRecentActivitiesByCursor() filtering and ordering so
new databases receive the required index.
🔗 관련 이슈 (Related Issue)
📝 작업 내용
운영 배포 중 Flyway validate 실패로 애플리케이션이 부팅되지 않아 배포와 롤백이 모두 실패한 문제를 해결합니다.
원인
V010이 MySQL에서 지원하지 않는 조건부 DDL을 사용했습니다.DROP COLUMN IF EXISTS,CREATE INDEX IF NOT EXISTS,DROP INDEX IF EXISTS는 모두 MariaDB 전용 확장이며 MySQL에는 존재하지 않습니다.MySQL은 DDL에 트랜잭션이 없어 마이그레이션이 중간에 실패하면
flyway_schema_history에 실패 이력만 남습니다. 이 이력이 있는 한validate-on-migrate: true설정에서는 어떤 이미지를 올려도 부팅이 차단되므로, 이전 이미지로의 롤백까지 함께 실패했습니다.변경 사항
V010:ALTER TABLE project_member DROP COLUMN IF EXISTS last_activity_read_at제거ProjectMember엔티티와 운영 DB 어디에도 존재하지 않아 애초에 불필요한 문장이었습니다.CREATE TABLE project_activity_read한 문장만 남습니다.V011: 삭제idx_activity_log_project_created_id는 운영 DB에 이미 존재합니다.FK273xmgexdxj7yu432gth17luq (project_id → project.id)를 떠받치는 유일한 인덱스라 제거할 수 없습니다(ERROR 1553). MySQL에는 조건부 인덱스 생성 문법이 없으므로 마이그레이션 대상에서 제외했습니다.선행된 운영 DB 조치 (머지 전 수동 수행 완료)
현재
flyway_schema_history는8(BASELINE),009두 행만 남아 있으며 둘 다success = 1입니다. 머지 후 Flyway는V010하나만 실행합니다.토큰이 부족해서 코파일럿을 이용했더니.. sql문 생성시 mariadb 문법을 섞어버렸네요.. ㅠ
✅ PR 체크리스트
Summary by CodeRabbit