발단

  1. 데이터베이스 정보를 조회하는게 엄——청 느렸음 (대략 5분 정도)
  2. 문제를 확인 해보았을때 다음과 같은 문제점들이 있었음
    1. 쿼리안의 쿼리 [물건 → 포함된 물건 → 포함된 물건 정보 → …]
    2. 3중 조인 + 조건
    3. 인덱스 없음
  3. 이를 개선하고자 다음과 같은 시도를 거침
    1. 최초 쿼리까지는 동기적으로 수행하고 내부 데이터를 가져오는 쿼리들은 비동기로 수행
    2. 2중 조인에서 정보를 모두 찾을수 있어 축약
      1. 이는 데이터베이스 마이그레이션을 선행한 덕분임.
    3. 검색되는 컬럼에 대해서 인덱스 추가…
      1. 여기서 문제가 발생함

문제

  1. 실시간으로 운영중인 데이터베이스에 인덱스를 추가함
  2. 몇 초면 끝날것이라고 예상했던 데이터베이스 인덱스 추가 작업이 X분 이상 지속됨
  3. 그동안 데이터베이스를 향한 모든 요청이 홀딩됨 → [이거 왜 안돼요?]

원인

  1. 일반적인 데이터베이스 인덱스는 B-Tree를 사용함
  2. 인덱스 추가과정은 다음과 같음
    1. 테이블 스캔 → 테이블 락 or MVCC(다중 동시성 제어) → 인덱스 생성
    2. 이때 모든 기록은 트랜잭션 로그에 기록됨
  3. 실시간으로 운영중인 데이터베이스에 인덱스를 추가하면 정합성 보장을 위해서 테이블에 락이 걸림
    1. 인덱스 생성시 데이터가 변하면 안되기 때문…
  4. 락이 걸린 테이블에 요청이 들어오면 모두 대기 상태로 전환됨
    1. 자원 경쟁이 발생함으로써 데이터베이스 속도 저하
    2. 실시간으로 들어오는 데이터에 대해서도 기록을 해야 하기 때문에 트랜잭션 로그는 더욱 복잡해지고 많아짐 → 오버헤드 발생
  5. 이는 선행 세션의 작업이 완료 될때 까지 후행 세션이 락을 획득하려고 시도하고 대기 한다는 것을 의미
  6. 선행 작업 세션은 테이블 컬럼의 모든 정보를 업데이트 해야 되기 때문에 인덱스가 모두 업데이트 될때 까지 후행 세션의 요청들을 대기 로 전환 함
  7. 그래서 [이거 왜 안돼요?, 이거 멈췄어요!] 하고 대공황이 발생함;

해결

  1. 하루안에 해결 해야 하기 때문에 우선 서비스를 복구하기 위해 인덱스 추가를 취소하고 가장 빠른 해결책인 사용량이 낮을때 인덱스 추가를 시도함
  2. 요청이 거의 없던 때라 1분 이내에 모든 인덱스가 추가되었음