update쿼리는 락을 건다. 인덱스에!

rejs·2025년 12월 29일

문제이해

explain format =json
UPDATE reservations
JOIN screenings using (screening_id)
SET status = 'CANCELLED'
WHERE start_time < NOW() and status = 'PENDING';
UPDATE reservations
SET status = 'CANCELLED'
WHERE status = 'PENDING' and created_at < NOW() -INTERVAL 10 MINUTE;

DB를 폴링하면서 10분이 지나도록 예매가 완료(결제)되지 못하거나, 상영시간전까지 처리되지 못한 예매를 모두 정리합니다.

이 쿼리의 실행계획은 어떻게 될까요

문제

{
  "query_block": {
    "select_id": 1,
    "table": {
      "update": 1,
      "table_name": "reservations",
      "access_type": "index",
      "key": "PRIMARY",
      "key_length": "",
      "used_key_parts": ["reservation_id"],
      "rows": 40080,
      "attached_condition": "reservations.`status` = 'PENDING' and reservations.created_at < current_timestamp() - interval 10 minute"
    }
  }
}

인덱스를 처음부터 끝까지 다 읽는 군요
그거 아십니까?

innoDB는 인덱스에 락을 건다는 사실 말입니다.

SELECT trx_id, trx_rows_locked, trx_rows_modified FROM information_schema.INNODB_TRX;

update가 수정하는 것은 8천개밖에 되지 않는데!
락에 걸린 데이터는 40000개나 됩니다.

안타까운 사실은 이 쿼리는 스케줄러에 의해 폴링될 것이란 점입니다.

데이터가 크면 클수록 아주 끔찍한 재앙을 초래할 것입니다.

0개의 댓글