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

그래프

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

사례5건

5건 중 1~5번째

  1. 증상

    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에 자동으로 달리는 기존 코멘트의 체크리스트에 이번 확인 항목을 더한다.
  2. 증상

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

    촉발

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

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

    2023년 4월 4일 09:13 UTC 에 배포를 시작하고 7분 뒤인 09:20 UTC 에 서비스 성능 저하가 보였다. 운영에서 실행한 마이그레이션이 Transactions 테이블 전체를 잠근 상태였다.

    촉발

    2023년 4월 4일 09:13 UTC 에 성능을 높이려고, 소프트 삭제된 행을 빼고 Transactions 테이블의 인덱스를 다시 만드는 마이그레이션을 배포했다.

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

    배포를 시작하고 7분 뒤인 09:20 UTC 에 서비스 성능 저하를 알아챘다.

    조치
    • 마이그레이션을 죽였지만 Transactions 테이블은 잠긴 채로 남았다.
    • 쿼리를 줄이려고 프런트엔드를 점검 모드로 돌렸다. 사용자에게는 분명한 안내 문구가 보였다.
    • 데이터베이스에 붙어 있던 다른 연결을 닫았다.
    • 새 인덱스 생성을 취소하고 10:00 UTC 부터 옛 인덱스를 되살렸으며, 10:05 UTC 에 복원이 끝나 성능이 정상으로 돌아왔다.
    • 10:08 UTC 에 프런트엔드를 되살리고 문제가 해결됐다고 공식으로 확인했다.
    후속 조치
    • vegeta 같은 도구로 로컬에서 운영 부하를 흉내 내는 스크립트를 더한다.
    • 이런 마이그레이션은 정해진 점검 시간대에 돌린다.
    • 앞으로 마이그레이션은 새 인덱스를 먼저 만들고 옛 인덱스를 나중에 지운다.
    • PR 을 머지하기 전에 다른 엔지니어의 리뷰를 꼭 받는다. 이번 PR 은 팀에 공유됐지만 리뷰되지 않았다.
    교훈

    옛 인덱스를 지우고 새 인덱스를 만드는 방식은 쿼리가 끊임없이 들어오는 테이블에서 너무 낙관적이었다. 로컬과 staging 에서 시험해도 부하가 걸린 환경에서 마이그레이션을 돌려 볼 도구가 없으면 이런 문제를 미리 잡지 못한다. 문제를 빨리 알아채고 엔지니어 두 명이 함께 조사한 것과, 사용자에게 분명한 안내를 보이면서 영향을 줄인 프런트엔드 점검 모드는 도움이 됐다.

  4. 증상

    2021년 11월 27일 20:40 UTC 부터 GitHub Actions, API 요청, Codespaces, Git 작업, Issues, GitHub Packages, GitHub Pages, Pull Requests, Webhooks 의 가용성이 떨어졌다. 큰 MySQL 테이블의 스키마 마이그레이션이 마지막 rename 단계를 실행하던 때였다.

    촉발

    큰 MySQL 테이블의 스키마 마이그레이션이 마지막 단계로 갱신한 테이블을 제자리로 옮기는 rename 을 실행했다. 이때 읽기 복제본 상당수가 semaphore deadlock 에 걸렸다.

    원인
    구성 요소
    기여 요인
    조치
    • 정상 상태인 내부용 복제본을 모두 운영 경로로 올려 용량을 늘렸다. 이것만으로는 완전히 복구되지 않았다.
    • crash-recovery 를 되풀이하는 복제본에서 운영 트래픽을 미리 빼고, 그 복제본이 테이블 rename 을 끝까지 처리할 때까지 기다렸다.
    • 회복한 복제본을 운영에 다시 넣어 정상 운영에 필요한 용량을 되찾았다.
    후속 조치
    • 클러스터를 기능별로 나누는 작업을 계속 우선해서, 마이그레이션을 샤드 하나에서 카나리 모드로 먼저 돌릴 수 있게 한다.
    • 클러스터마다 여유 용량을 더 크게 잡도록 내부 절차를 고친다.
    • 이 문제를 막는 방법을 더 알게 될 때까지 스키마 마이그레이션을 멈춘다.
    • 이번 장애가 일어난 구체적인 조건을 계속 조사한다.
    • 마이그레이션 도구를 시험하면서 이런 상황에서 도구를 고칠 점을 가려낸다.
  5. 증상

    계획된 데이터베이스 스키마 마이그레이션이 시작된 직후 API 요청에서 타임아웃이 난다는 알림이 왔다. API 는 15초쯤 요청을 받지 못하다가 마이그레이션이 끝나자 다시 살아났다.

    촉발

    Pro 제품의 인보이스 기능을 만들면서 이름을 바꾼 빈 테이블에서 외래 키 제약을 지우고 다시 만드는 마이그레이션을 배포했다. 그때 참조되는 테이블에서 오래 도는 읽기 쿼리가 실행 중이었다.

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

    스키마 마이그레이션이 시작된 직후 API 요청에서 타임아웃이 난다는 알림이 왔다.

    교훈

    앱에서 오래 도는 쿼리와 트랜잭션을 없애고, 분석 쿼리는 비동기로 갱신되는 복제본에서 돌린다. log_min_duration_statement 와 log_lock_waits 를 설정하면 이런 문제가 장애로 번지기 전에 찾을 수 있다. 마이그레이션 스크립트에는 앱이 견딜 수 있는 만큼의 lock_timeout 을 둔다. 앱을 멈추는 것보다 배포를 중단하는 편이 낫다. 스키마 변경을 잘게 나누면 문제를 진단하기 쉽고, DDL 을 감싼 트랜잭션이 짧아져 잠금을 오래 잡지 않는다. Postgres 는 릴리스마다 잠금 코드가 나아지므로 최신으로 유지한다. 운영 데이터베이스에 쿼리를 날릴 수 있는 콘솔을 쓰는 개발자는 아주 조심해야 한다. 트랜잭션을 열어 둔 채 자리를 비우면 누군가 스키마 변경을 배포할 때 장애가 난다.

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

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

원인별2