메모장

블로그 이미지

동팡

https://github.com/ehdvudee

MySQL insert, Lock wait timeout exceeded 트러블슈팅

개발관련/삽질 2022. 2. 22. 00:52

MySQL 정보

  • 버전: 5.7
  • 트랜잭션 격리 수준: Default(repeatable read)

장애 현상

  • A 트랜잭션에서 T1 테이블에 delete 쿼리 진행할 때 B 트랜잭션에서 T1 테이블에 insert 쿼리가 lock wait 발생

원인-1(첫 번째 분석)

  • delete 쿼리의 실행 계획에서 풀 테이블 스캔 발생
  • Where 절이 pk로 구성되어 있어도 옵티마이저는 풀 테이블 스캔이 유리하다고 판단(풀 테이블 스캔은 멀티 블록 스캔이고 인덱스는 싱글 블록 스캔이니 일정 분기점 이상 부터는 인덱스 스캔보다는 풀테이블 스캔이 유리함)
  • MySQL에서 로우에 락이 잡히는 기준은 스캐닝된 인덱스 레코드[1]

위의 분석으로 알 수 있는 사항은 다음과 같다.

  • T1 테이블의 모든 로우는 락이 잡혔으며
  • 락이 잡혀있는 동안 다른 세션(트랜잭션)에서 T1 테이블의 모든 로우는 delete/update 불가능하다.

근데 insert는 왜 안돼??? 격리 수준을 read committed 했을 때는 insert가 잘 된다.

원인-2(두 번째 분석)

  • 현재 MySQL의 격리 수준은 repeatable read이다.
  • delete 쿼리를 진행할 때 Next-Key-Lock이 잡혔으며[2],
  • Repeatable read에서 Next-key-lock으로 인해 positive infinity 레코드 까지 락이 걸렸고,
  • 해당 락으로 인해 insert에 lock wait이 발생한다.
  • 위의 락으로 본의 아니게 팬텀 로우를 방지한다

기타 특이 사항

  • delete할 때 풀 테이블 스캔이 아닌 유니크 스캔을 할 때 insert에 lock wait이 발생하지 않는다.
  • ㄴ유니크 스캔을 하면 lock wait 발생하지 않는게 웃기지 않나?? Repeatable read에서 팬텀 로우를 막아준다는데 안 막아준다. ㅈㄴ 어불성설이다ㅋㅋㅋㅋㅋㅋㅋㅋ(아 근데 이 부분에서 lock wait 발생하면 동시성 ㅈ됨)
  • read committed 격리 수준일 때 되는 이유는 단순하다. gap lock, next-key-lock이 비활성화 되어 있기 때문이다.
  • 반대 상황도 Lock이 발생한다. 1) insert 2) delete 풀 테이블 스캔

기타 주의 사항

  • 인덱스 조건없이 쿼리하는 경우 테이블 락 발생
  • 2개 이상의 세션에서 동일한 인덱스 키를 사용하여 다른 행의 레코드에 엑세스할 때 락 충돌할 수 있다(동일한 스캔 범위가 있는 경우 lock wait 발생)
  • 인덱스 효율이 좋지 않으면 락 범위가 넓어진다.
  • 아무리 PK/유니크 인덱스를 사용하여도 옵티마이저 판단하에 풀 테이블 스캔으로 테이블 락이 발생할 수 있다(지금 상황).

재연

1. 테이블 생성

mysql> create table test_tt(t1 int primary key auto_increment, t2 int, t3 int); 
Query OK, 0 rows affected (0.09 sec)

2. 테스트 데이터 삽입/조회

mysql> insert into test_tt(t2, t3) values (1,2); Query OK, 1 row affected (0.00 sec) 
... 

mysql> select * from test_tt;
+----+------+------+
| t1 | t2   | t3   |
+----+------+------+
|  1 |    1 |    2 |
|  2 |    1 |    2 |
|  4 |    1 |    2 |
| 31 |    1 |    2 |
| 32 |    1 |    2 |
| 33 |    1 |    2 |
| 34 |    1 |    2 |
| 35 |    1 |    2 |
| 36 |    1 |    2 |
| 37 |    1 |    2 |
| 38 |    1 |    2 |
| 39 |    1 |    2 |
| 40 |    1 |    2 |
| 41 |    1 |    2 |
| 42 |    1 |    2 |
| 43 |    1 |    2 |
| 44 |    1 |    2 |
+----+------+------+
17 rows in set (0.00 sec)

3. 삭제 실행(세션 1, 트랜잭션 시작, 삭제실행)

mysql> explain delete from test_tt where t1 in(31,32,33,34);
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | DELETE      | test_tt | NULL       | ALL  | PRIMARY       | NULL | NULL    | NULL |    4 |   100.00 | Using where |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set (0.00 sec)

4. 삽입 실행(세션2, 트랜잭션 시작)

mysql> insert into test_tt(t2, t3) values (1,2);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

5. DB 락 현황 조회 결과

mysql> select * from information_schema.innodb_locks;
+--------------+-------------+-----------+-----------+-------------------+------------+------------+-----------+----------+------------------------+
| lock_id      | lock_trx_id | lock_mode | lock_type | lock_table        | lock_index | lock_space | lock_page | lock_rec | lock_data              |
+--------------+-------------+-----------+-----------+-------------------+------------+------------+-----------+----------+------------------------+
| 10586:43:3:1 | 10586       | X         | RECORD    | `mysql`.`test_tt` | PRIMARY    |         43 |         3 |        1 | supremum pseudo-record |
| 10581:43:3:1 | 10581       | X         | RECORD    | `mysql`.`test_tt` | PRIMARY    |         43 |         3 |        1 | supremum pseudo-record |
+--------------+-------------+-----------+-----------+-------------------+------------+------------+-----------+----------+------------------------+
2 rows in set, 1 warning (0.00 sec)
 
mysql> select * from information_schema.innodb_lock_waits;
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 10586             | 10586:43:3:1      | 10581           | 10581:43:3:1     |
+-------------------+-------------------+-----------------+------------------+
1 row in set, 1 warning (0.00 sec)

 

참고문헌

  • [1]MySQL Doc, locking read
  • [2]MySQL Doc, InnoDB Locking
  • row lock 관련 아티클
  • MySQL Doc,Transaction Isolation Levels, read committed 관련
저작자표시 비영리 (새창열림)

'개발관련 > 삽질' 카테고리의 다른 글

Vanilla(Pure)-JavaSciprt 게시판 페이징 - 1(기본/응용)  (0) 2021.07.27
hashicorp사의 Vault(볼트) - Tutorial-Docker - 4  (0) 2021.07.06
hashicorp사의 Vault(볼트) - Tutorial-Real(With-REST-API) - 3  (0) 2021.07.05
hashicorp사의 Vault(볼트) - Tutorial-Dev(With-커맨드) - 2  (0) 2021.07.01
hashicorp사의 Vault(볼트) - 개요 - 1  (0) 2021.06.29
Posted by 동팡
블로그 이미지

https://github.com/ehdvudee

by 동팡

공지사항

    최근...

  • 포스트
  • 댓글
  • 트랙백
  • 더 보기

태그

  • vault tutorial
  • 네이버 클라우드 개발자 면접
  • 네이버 비즈니스 플랫폼
  • 책리뷰
  • Thread-safe
  • 볼트란
  • 개발자 이직
  • What is Vault
  • LoRaWA
  • 개발자 글쓰기 책
  • vault
  • 네이버 클라우드
  • 하시콥 볼트
  • 이직 정보 공유
  • Hashicorp
  • 경력 채용
  • 간단리뷰
  • Secret Sharing
  • NBP
  • 개발자 책리뷰
  • java
  • Shamir Secret Sharing
  • 개발자 준비
  • 자바
  • Spring
  • vault 개요
  • Secret Sharing 이론
  • 글쓰기 가이드
  • 이직 느낀점
  • 네이버 클라우드 이직

글 보관함

«   2025/05   »
일 월 화 수 목 금 토
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

링크

카테고리

메모장 (73)
개발관련 (71)
삽질 (26)
(과거)메모 (27)
강의 (0)
회고 (9)
책 리뷰 (9)
블로그 관리 글(비공개) (0)
일상 (2)
기타 (0)
책 리뷰 (1)
회고 (0)

카운터

Total
Today
Yesterday
방명록 : 관리자 : 글쓰기
동팡's Blog is powered by daumkakao
Skin info material T Mark3 by 뭐하라
favicon

메모장

https://github.com/ehdvudee

  • 태그
  • 링크 추가
  • 방명록

관리자 메뉴

  • 관리자 모드
  • 글쓰기
  • 메모장 (73)
    • 개발관련 (71)
      • 삽질 (26)
      • (과거)메모 (27)
      • 강의 (0)
      • 회고 (9)
      • 책 리뷰 (9)
    • 블로그 관리 글(비공개) (0)
    • 일상 (2)
      • 기타 (0)
      • 책 리뷰 (1)
      • 회고 (0)

카테고리

PC화면 보기 티스토리 Daum

티스토리툴바