사례2건
2건 중 1~2번째
- 증상
미사용 인덱스를 INVISIBLE 로 바꾸는 ALTER 문을 실행할 때마다 Aurora MySQL 클러스터의 Reader 3대에서 CPU 와 ReadIOPS 가 동시에 튀었다. 같은 시각 Writer 의 지표는 평소와 같았다.
- 촉발
DB팀이 미사용 인덱스를 정리하려고 Aurora MySQL 3.10.x 클러스터의 Writer 에서 인덱스를 하나씩 시간 간격을 두고 ALTER INDEX ... INVISIBLE 로 바꿨다.
- 원인
- 구성 요소
- 기여 요인
- 감지
CloudWatch 에서 ALTER INDEX INVISIBLE 을 실행한 세 번의 시각에 Reader 의 CPU 와 ReadIOPS 스파이크가 하나씩 정확히 겹치는 것을 보고 알아챘다.
- 후속 조치
- Aurora MySQL 3.14 로 바로 올리기는 어려우므로, 이 수정이 들어간 다음 LTS 버전이 나오면 그 버전으로 업그레이드한다.
- 그 전까지 인덱스 DDL 은 트래픽이 적은 시간대에 실행한다.
- 인덱스 여러 개를 바꿀 때는 한 ALTER 문으로 묶어 Reader 버퍼풀 무효화를 N 번에서 1 번으로 줄인다.
- 교훈
Aurora MySQL 에서 인덱스를 INVISIBLE 로 바꾸는 작업은 메타데이터만 바꾸므로 부하가 없다는 생각은 Writer 에서만 맞았다. 3.08.0 부터 3.14 이전 버전에서는 인덱스 DDL 을 Reader 버퍼풀을 비우는 작업으로 보고 운영한다. 행이 많고 트래픽이 높은 테이블일수록 버퍼풀이 다시 채워지는 동안 ReadIOPS 와 CPU 가 크게 오를 수 있다. 미사용 인덱스를 고를 때는 performance_schema.table_io_waits_summary_by_index_usage 를 모든 노드에서 확인한다. 노드마다 쿼리 패턴이 달라서, Writer 에서 count_read 가 0 인 인덱스를 어떤 Reader 는 자주 쓸 수 있다. INNODB_BUFFER_PAGE 조회는 버퍼풀 전체를 훑으므로 버퍼풀이 큰 인스턴스에서는 몇 초씩 걸리고 부하도 준다. 운영 중에는 꼭 필요할 때만 조회한다.
- 증상
계획된 데이터베이스 스키마 마이그레이션이 시작된 직후 API 요청에서 타임아웃이 난다는 알림이 왔다. API 는 15초쯤 요청을 받지 못하다가 마이그레이션이 끝나자 다시 살아났다.
- 촉발
Pro 제품의 인보이스 기능을 만들면서 이름을 바꾼 빈 테이블에서 외래 키 제약을 지우고 다시 만드는 마이그레이션을 배포했다. 그때 참조되는 테이블에서 오래 도는 읽기 쿼리가 실행 중이었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
스키마 마이그레이션이 시작된 직후 API 요청에서 타임아웃이 난다는 알림이 왔다.
- 교훈
앱에서 오래 도는 쿼리와 트랜잭션을 없애고, 분석 쿼리는 비동기로 갱신되는 복제본에서 돌린다. log_min_duration_statement 와 log_lock_waits 를 설정하면 이런 문제가 장애로 번지기 전에 찾을 수 있다. 마이그레이션 스크립트에는 앱이 견딜 수 있는 만큼의 lock_timeout 을 둔다. 앱을 멈추는 것보다 배포를 중단하는 편이 낫다. 스키마 변경을 잘게 나누면 문제를 진단하기 쉽고, DDL 을 감싼 트랜잭션이 짧아져 잠금을 오래 잡지 않는다. Postgres 는 릴리스마다 잠금 코드가 나아지므로 최신으로 유지한다. 운영 데이터베이스에 쿼리를 날릴 수 있는 콘솔을 쓰는 개발자는 아주 조심해야 한다. 트랜잭션을 열어 둔 채 자리를 비우면 누군가 스키마 변경을 배포할 때 장애가 난다.
이 2건에서 가장 많이 나오는 구성 요소: 데이터베이스, 스키마 마이그레이션. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.