한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

게임 렉 백서 › L12 데이터베이스

핫 로우 잠금 경합 Hot row lock contention

원인 ID db-hot-row · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

그림과 실험이 있는 원본 카드로 열기 →

모두가 같은 행(길드 창고, 경매장 인기 아이템, 서버 전체 카운터)을 고치려 하면 한 명씩만 잠금을 얻습니다.

왜 이벤트·인기 아이템으로 같은 행에 수정이 몰림 → 그러면 잠금을 얻을 때까지 요청이 대기 → 화면에서는 거래 실패, “잠시 후 다시 시도”, 타임아웃

증상
씹힘·롤백, 입력 지연
요인
정체, 지연
누가 겪나
특정 기능만
언제
사람이 몰릴 때
담당
주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라
게임개발팀 할 일
행을 나누기(샤딩된 카운터), 트랜잭션 짧게, 메모리에서 모아 한 번에 반영.
인프라팀 할 일
행 잠금 대기 시간·건수를 모니터링해 경합이 몰리는 행을 찾아 공유.
수치 감각
한 요청이 잠금을 10ms 잡고 있으면 그 행은 1초에 최대 100번만 고칠 수 있습니다. 트랜잭션 안에 다른 서버 왕복이 끼면 그만큼 더 줄어듭니다.
그래프에서는
인원·부하를 따라 오름 · 행 잠금 대기 수·시간
확인할 곳
MySQL은 Innodb_row_lock_waits·Innodb_row_lock_time 증가량과 Innodb_row_lock_current_waits를 보고, sys.innodb_lock_waits로 누가 누구를 기다리는지 찾음. PostgreSQL은 pg_stat_activity에서 wait_event_type이 Lock인 세션, pg_locks에서 granted가 false인 요청을 보고 log_lock_waits(기본 꺼짐)를 켜면 오래 기다린 잠금이 로그에 남음
이러면 맞음
이벤트·인원을 따라 잠금 대기가 가파르게 늘고 기다리는 요청 대부분이 같은 테이블의 같은 행(같은 키)을 가리킴
이러면 아님
대기가 여러 테이블·행에 고르게 흩어지면 디스크·CPU 포화 쪽. 한 세션이 잠금을 오래 잡고 놓지 않으면 오래 열린 트랜잭션(db-long-tx)
확인 수단
인프라 도구로 확인(게임 코드 불필요)

출처

  1. InnoDB Locking MySQL
    한 트랜잭션이 행(인덱스 레코드)에 잠금을 걸면 다른 트랜잭션은 그 행을 고치지 못하고 기다림
  2. How to Minimize and Handle Deadlocks MySQL
    트랜잭션을 작고 짧게 유지하고 관련 변경 직후 바로 커밋해 충돌을 줄이라는 권고
  3. Server Status Variables MySQL
    Innodb_row_lock_waits·Innodb_row_lock_time으로 행 잠금 대기 횟수와 시간, Innodb_row_lock_current_waits로 지금 기다리는 수를 확인
  4. The innodb_lock_waits and x$innodb_lock_waits Views MySQL
    기다리는 쿼리(waiting_query)와 막고 있는 세션(blocking_pid), 대기 시간(wait_age)
  5. The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
    pg_stat_activity의 wait_event_type: Lock이면 무거운 잠금을 기다리는 중
  6. pg_locks (PostgreSQL Documentation) PostgreSQL
    granted가 false면 그 프로세스가 잠금을 얻으려고 기다리는 중
  7. Error Reporting and Logging (PostgreSQL Documentation) PostgreSQL
    log_lock_waits: deadlock_timeout보다 오래 잠금을 기다리면 로그를 남김, 기본 꺼짐

함께 보면 좋은 원인

같은 층: L12 데이터베이스

같은 증상(씹힘·롤백)의 다른 층 원인

그림과 실험이 있는 원본 카드 보기