Incident Library
적용된 필터 구성 요소스키마 마이그레이션모두 풀기검색어 없이 필터만 적용한 목록입니다. 최근 사례부터입니다.
추천 필터 검색하면 검색어에서 찾은 분류 값이 여기에 나옵니다.

그래프

  • 원인
  • 구성 요소
  • 증상
  • 기여 요인
  • 사례

사례8건

8건 중 1~5번째

  1. 증상

    미사용 인덱스를 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 조회는 버퍼풀 전체를 훑으므로 버퍼풀이 큰 인스턴스에서는 몇 초씩 걸리고 부하도 준다. 운영 중에는 꼭 필요할 때만 조회한다.

  2. 증상

    drop_table 마이그레이션을 실행한 직후부터 데이터베이스 쿼리가 막히기 시작했고, crowdworks.jp에는 1분쯤 접속이 잘 되지 않았다. 마이그레이션은 끝내 타임아웃으로 실패했고 서비스는 저절로 복구됐다.

    촉발

    이미 쓰지 않는 테이블을 지우려고 drop_table 마이그레이션을 실행했다. 이 테이블에는 트래픽이 매우 많은 테이블을 가리키는 외래 키 제약이 걸려 있었다.

    원인
    구성 요소
    기여 요인
    –
    후속 조치
    • 대상 마이그레이션은 execute 'SET SESSION lock_wait_timeout = 3' 으로 MDL 대기 상한을 줄여, 대기가 길어지기 전에 실패하게 한다. 3초는 운영하면서 조정할 임시 값이다.
    • execute는 change에서 되돌릴 수 없어 롤백 때 ActiveRecord::IrreversibleMigration 이 나므로, def change 대신 def up 과 def down 으로 쓴다. 롤백 쪽 DDL도 같은 MDL을 잡으므로 up과 down 모두 대상 DDL 앞에 설정을 둔다.
    • 중간에 실패해 일부만 적용되는 일을 피하려고 마이그레이션 하나에 대상 DDL은 하나만 둔다.
    • 실패할 때 다른 마이그레이션까지 휩쓸리지 않도록 대상 DDL을 담은 마이그레이션은 따로 릴리스한다.
    • 대상 마이그레이션은 트래픽이 적은 시간대에 실행한다.
    • 대상 조건과 대응 방법의 자세한 내용은 db/migrate/README.md 에 둔다.
    • AGENTS.md 의 참조 표에 db/migrate/ → db/migrate/README.md 한 줄을 더해 Copilot과 AI 에이전트가 리뷰할 때 이 규칙을 보게 한다.
    • db/migrate/** 를 바꾼 PR에 자동으로 달리는 기존 코멘트의 체크리스트에 이번 확인 항목을 더한다.
  3. 증상

    Railway 백엔드 API 가 트래픽을 받지 못해 대시보드 접속, CLI 작업, GitHub 기반 배포 처리, 로그인, API 가 멈췄다. 이미 돌고 있던 배포는 계속 온라인이었고, 이 시스템들을 쓰지 않은 사용자는 영향을 받지 않았다.

    촉발

    엔지니어들이 15:03 UTC 에 데이터 마이그레이션이 들어간 데이터베이스 스키마 변경을 머지했다. 이 마이그레이션은 약 10억 행이 있고 많이 쓰는 테이블에 nullable 열을 더하는 것이었다.

    원인
    구성 요소
    기여 요인
    후속 조치
    • 데이터베이스 연결 수를 늘리고, PgBouncer 가 그 한도 안에서 동작하도록 다시 설정한다.
    • 오래 도는 쿼리를 고쳐 행 잠금 문제가 다시 나지 않게 한다.
  4. 증상

    2024년 10월 10일 오후 3시 42분부터 4시 4분 PT까지 Sentry US 의 사이트와 이벤트 수집을 모두 쓸 수 없었다. 상태 페이지는 Postgres 데이터베이스 문제로 사이트를 쓸 수 없다고 알렸다.

    촉발

    RunSQL 명령으로 실행한 데이터베이스 마이그레이션에 잠금 타임아웃과 구문 타임아웃이 걸려 있지 않아 쿼리가 오래 돌았다.

    원인
    구성 요소
    기여 요인
    조치
    • 수정을 적용했고, 대시보드와 이벤트 수집이 회복하기 시작했다.
    후속 조치
    • 마이그레이션 프레임워크 안의 더 견고한 방법으로 바꿔 RunSQL 명령을 아예 없앤다.
    • 데이터베이스 프레임워크를 최신 버전으로 올린다. 새 버전은 전에 RunSQL 로 하던 작업 일부를 직접 처리한다.
    • 마이그레이션 중에 잠금이나 타임아웃 문제가 생겼을 때 복구를 안내하는 런북을 만들었다.
    • 더 빨리 대응하고 앞으로의 중단 시간을 줄이도록 알림과 관측 도구를 보강했다.
  5. 증상

    2023년 9월 7일 TANF-app 의 sprint 80 운영 배포가 실패했고, 9월 20일 sprint 82 배포는 디스크 공간 오류로 실패했다. 그 뒤 11월 9일까지 운영에 배포하지 못했다.

    촉발

    2023년 9월 7일 sprint 80 배포에서 이미 배포된 마이그레이션 search_indexes 0016 을 지웠고, 9월 20일 sprint 82 배포가 이 마이그레이션을 다시 만들어 큰 마이그레이션 0017 과 함께 운영 데이터베이스에서 돌렸다.

    원인
    구성 요소
    기여 요인
    감지

    운영 배포가 실패하면서 드러났다. 9월 7일 sprint 80 배포와 9월 20일 sprint 82 배포가 차례로 실패했고, 9월 20일 배포에서 디스크 공간 오류가 났다.

    조치
    • 11월 8일 운영 데이터베이스 인스턴스 크기를 키우고 마이그레이션을 다시 돌렸다. 이번에는 빈 문자열을 정수로 바꾸는 오류로 마이그레이션이 실패했다.
    • 운영 데이터베이스의 백업을 만들었다.
    • `search_indexes` 테이블을 모두 비웠다. 팀은 여기서 운영 데이터를 잃는 것을 걱정하지 않았다.
    • sprint 82 릴리스를 다시 배포해 운영을 sprint 82 로 되살렸고, 배포가 다시 가능해졌다.
    • 빈 문자열 버그를 고쳤다.
    후속 조치
    • 데이터베이스 문제 해결 절차를 기술 문서에 더한다.
    • 위키 페이지와 운영 플레이북에 흔한 문제와 대응을 정리한다.
    • Failed-Deployment-Troubleshooting 문서에 데이터베이스 문제 절을 만들고 cf revisions 명령을 적는다.
    • 운영에 직접 한 변경을 모은 GitHub 레포를 만들어, 비슷한 문제가 다시 날 때 길잡이로 쓴다.
    • 운영 디버깅 세션의 터미널 출력을 저장한다.
    • 코드 리뷰에서 지킬 Django 마이그레이션 모범 사례를 만든다.
    • develop 에 머지된 마이그레이션은 고치지 않고, 그 시점부터 모델을 바꾸는 새 마이그레이션을 쓴다.
    • 자동 생성된 마이그레이션 이름을 알아보기 쉬운 이름으로 바꾼다. 이름만 보고 내용을 알 수 없으면 조사하기 어렵다.
    • 자동 생성 마이그레이션은 모델 변경 하나에 하나만 두고, PR 하나에서 모델을 여러 번 바꾸면 마이그레이션을 다시 생성한다.
    • 시험에 쓸 데이터베이스 시딩과 백업을 어떻게 할지 논의 자리를 만든다.
    교훈

    계획에 없던 일이라 많은 개발자가 손을 보태야 했고, 팀이 작아 분야마다 모든 사람이 필요했다. 팀은 문제와 대응을 일찍 문서로 남겨 더 적은 사람으로 대응할 수 있게 하자고 했다. 작업 중인 코드를 raft, qasp, sandbox 환경에 배포한 뒤 마이그레이션을 바꾸면 그 환경에서 충돌이 난다. 대용량 데이터와 공백 채움이 없는 레코드 같은 예외 상황은 시험하지 않았고, 개인정보를 지운 운영 데이터베이스 사본이 있으면 실제 데이터로 더 많이 시험할 수 있다.

내 클러스터에도 있는지 확인하기

이 8건에서 가장 많이 나오는 구성 요소: 데이터베이스, 스키마 마이그레이션. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.

원인별2

소프트웨어 결함2건

  1. IL-0451 Aurora MySQL 에서 인덱스를 INVISIBLE 로 바꿀 때마다 Reader 3대의 버퍼풀이 무효화돼 CPU 와 ReadIOPS 가 튀었다
    Daangn2026
  2. IL-0385 큰 MySQL 테이블의 스키마 마이그레이션 마지막 단계에서 읽기 복제본 다수가 semaphore deadlock 에 걸려 GitHub 핵심 서비스가 2시간 50분 저하됐다
    GitHub2021

배포 결함6건

  1. IL-0570 안 쓰는 테이블을 지우는 마이그레이션 직후 MySQL 쿼리가 막혀 crowdworks.jp에 1분쯤 접속하기 어려웠다
  2. IL-0369 데이터베이스 마이그레이션이 잠금에 막히는 동안 Railway 백엔드 복제본이 헬스 체크에 실패해 대시보드와 API 가 멈췄다
  3. IL-0554 데이터베이스 마이그레이션의 긴 쿼리가 Postgres 커넥션을 고갈시켜 Sentry US 의 사이트와 수집이 22분 동안 멈췄다
    Sentry2024
  4. IL-0523 TANF-app 의 운영 배포가 PostgreSQL 마이그레이션 실패로 두 달 동안 막힘
  5. IL-0524 인덱스를 다시 만드는 마이그레이션이 운영에서 Transactions 테이블을 잠가 Open Collective 서비스가 느려짐
  6. IL-0391 외래 키 제약을 다시 만드는 Postgres 마이그레이션이 잠금 대기열에 걸려 GoCardless API 가 15초쯤 멈췄다