Incident Library

IL-0301 37signals · 2022-06-27database

Basecamp 3 의 주 데이터베이스가 정시 부하에 락 경합으로 30초 만에 완전히 막혔다

2022년 6월 27일 13:00 UTC, 30초 사이에 Basecamp 3 의 주 데이터베이스가 완전히 막혔다. 이 시각은 Basecamp 3 가 각종 예약 알림을 대량으로 묶어 보내는 때였고, 부하가 큰 쿼리가 몰리면서 락 경합이 연쇄로 번졌다. 막힌 쿼리 수천 개가 기다리는 동안 새 쿼리 수천 개가 새 연결과 새 실행 스레드를 만들며 같은 락에 쌓였다. 서버 하드웨어가 스레드에 짓눌려 데이터베이스는 사실상 아무 일도 하지 못했다. 37signals 는 원인 하나를 집어낼 수 없었다고 밝혔다. Basecamp 3 가 빠르게 성장하면서 주 데이터베이스가 한계에 점점 다가갔고, 이날 처음으로 그 한계를 넘었다는 설명이다. 지난 1년의 지표를 다시 보니 알림을 울리지 않은 채 주 데이터베이스 부하를 서서히 늘린 성능 저하가 여러 건 있었다.

37signals 는 진행 보고 이메일을 늦추는 식으로 일부 기능을 멈췄지만 데이터베이스는 이미 감당할 수 있는 선을 넘어 있었다. 막힌 쿼리 수천 개를 종료하자 트랜잭션 롤백이 같은 락에서 막히면서 정체가 더 커졌다. 대기 중이던 복제본으로 페일오버하자 서비스가 돌아왔지만, 멈췄던 기능을 다시 켜는 동안 다른 요인이 섞인 같은 종류의 락 경합으로 다시 무너졌다. 그다음 Basecamp 3 를 유지보수 모드로 바꾸고 데이터베이스 쿼리 시간에 강제 상한을 걸자 정체가 풀렸다. 쿼리 시간 상한을 안전장치로 둔 채 기능을 하나씩 다시 켰고, 장애 시작 후 거의 세 시간 뒤인 15:49 UTC 에 정상화를 알렸다.

누적 중단 시간은 103분, 곧 1.7시간이었다. 데이터는 잃지 않았고 HEY, Basecamp 2, Basecamp Classic 을 비롯한 다른 제품은 영향을 받지 않았다.

심각도
–
영향 범위
Basecamp 3 was slow, showed errors and was down for 103 minutes in total between 13:00 and 15:49 UTC; HEY, Basecamp 2 and Basecamp Classic were not affected and no data was lost
영향 사용자
Basecamp 3 users
지역
–
감지까지
–
복구까지
2h 49m

증상

2022년 6월 27일 13:00 UTC 에 Basecamp 3 가 갑자기 아주 느려졌고 곧 오류 페이지를 보였다. 같은 30초 사이에 Basecamp 3 의 주 데이터베이스가 정상에서 완전한 정체 상태로 넘어갔다.

사용자 쪽에서는 일부 기능이 동작하기는 했지만 응답이 한참 걸렸다. Basecamp 2 와 Basecamp Classic 은 정상이었다. 그 뒤 Basecamp 3 의 모든 기능이 멈췄고, 몇 분 뒤 돌아온 듯하다가 다시 느려지며 오류를 보였다. 15:45 UTC 무렵에야 Basecamp 3 가 돌아와 그 상태를 유지했다.

데이터베이스 안에서는 13:00:00 과 13:00:30 UTC 사이에 락 경합이 연쇄로 번졌다. 수천 개의 쿼리가 락을 기다리며 막혀 있는 동안에도 수천 개의 새 쿼리가 계속 들어왔다. 새 쿼리 다수가 새 데이터베이스 연결을 열었고, 연결마다 새 실행 스레드가 생겨 같은 락에서 다시 막혔다. 서버 하드웨어는 수천 개의 실행 스레드에 짓눌렸다. 데이터베이스가 죽은 것은 아니었지만 동시 작업을 조율하는 비용에 묶여 사실상 아무 일도 진행하지 못했다.

37signals 는 먼저 주 데이터베이스의 부하를 덜려고 Basecamp 3 의 일부 기능을 멈췄지만, 데이터베이스는 이미 감당할 수 있는 선을 한참 넘은 뒤였다. 막힌 쿼리 수천 개를 종료하자 상황이 더 나빠졌다. 쿼리를 종료하면 그 트랜잭션 전체를 롤백해야 하는데, 롤백 자체가 비싼 작업이고 같은 락에서 다시 막혔기 때문이다.

대기 중이던 복제본 데이터베이스로 페일오버하자 Basecamp 3 가 돌아왔다. 37signals 는 조심스럽게 정상화를 알리고 멈췄던 기능을 다시 켰는데, 데이터베이스가 다시 무너졌다. 두 번째에는 다른 요인이 섞여 있었지만 결국 다시 높은 동시성에서 생긴 락 경합이었다.

증상 잠금 경합과 교착데이터베이스 과부하지연 시간 증가오류율 상승서비스 중단

원인

촉발
13:00 UTC 에 예약 알림을 대량으로 묶어 보내는 시각에 맞춰 부하가 큰 데이터베이스 쿼리가 한꺼번에 몰려들었고, 이 쿼리들이 주 데이터베이스에서 락 경합을 연쇄로 일으켰다.

감지

37signals 는 13:00:00 과 13:00:30 UTC 사이에 Basecamp 3 의 주 데이터베이스가 완전히 정체되는 것을 보고 곧바로 대응을 시작했다.

조치

후속 조치

교훈

37signals 는 이번 장애에 원인 하나가 없었다고 밝혔다. 시스템이 한계를 조금만 넘어도 순식간에 안정에서 불안정으로 넘어가는 지점이 있고, 그 지점은 특별한 계기 없이 성장과 함께 서서히 다가온다. 막힌 쿼리를 종료하는 일은 트랜잭션 롤백 때문에 같은 락에서 다시 막혀 정체를 키울 수 있다. 37signals 는 이 시스템을 잘 알면서도 결정적인 단서가 없고 데이터베이스 내부를 깊이 들여다볼 수단이 없어 확신을 갖고 대응하지 못했다고 썼다. 그래서 문제 하나를 고치는 대신 위험을 줄이고 확신을 쌓아 가는 길을 택했다.

출처

관련 사례

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

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: 데이터베이스. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.