Computer >> 컴퓨터 >  >> 프로그래밍 >> MySQL

MySQL 잠금 대기 시간 초과(Lock Wait Timeout) 오류 디버깅 방법

MySQL 잠금 대기 시간 초과(Lock Wait Timeout)란?

MySQL에서 'Lock wait timeout exceeded' 오류는 주로 특정 스레드(트랜잭션)가 레코드에 대한 잠금을 비정상적으로 오랫동안 점유하고 있을 때 발생합니다. 하나의 스레드가 일부 레코드를 매우 긴 시간 동안 붙잡고 있다면, 해당 레코드에 접근하려는 다른 트랜잭션은 기본 대기 시간(기본값 50초, innodb_lock_wait_timeout)이 초과될 때까지 기다리게 되며, 결국 이 오류와 함께 실패합니다.

따라서 문제를 해결하려면 먼저 어떤 트랜잭션이 잠금을 점유하고 있는지 파악하는 것이 핵심입니다.

SHOW ENGINE INNODB STATUS로 상태 확인하기

InnoDB 엔진의 전체 상태 및 세부 정보를 확인하려면 다음 쿼리를 실행합니다.

mysql> SHOW ENGINE INNODB STATUS;

실행하면 다음과 같은 출력 결과를 확인할 수 있습니다.

+--------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Type   | Name | Status                                                           |
+--------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| InnoDB |      |
=====================================
2018-10-23 09:55:05 0x19e8 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 7 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 2 srv_active, 0 srv_shutdown, 17805 srv_idle
srv_master_thread log flush and writes: 0
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 3
OS WAIT ARRAY INFO: signal count 3
RW-shared spins 0, rounds 0, OS waits 0
RW-excl spins 0, rounds 0, OS waits 0
RW-sx spins 0, rounds 0, OS waits 0
Spin rounds per wait: 0.00 RW-shared, 0.00 RW-excl, 0.00 RW-sx
------------
TRANSACTIONS
------------
Trx id counter 21000
Purge done for trx's n:o < 20998 undo n:o < 0 state: running but idle
History list length 3
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 283438498772800, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: wait Windows aio (insert buffer thread)
I/O thread 1 state: wait Windows aio (log thread)
I/O thread 2 state: wait Windows aio (read thread)
I/O thread 3 state: wait Windows aio (read thread)
I/O thread 4 state: wait Windows aio (read thread)
I/O thread 5 state: wait Windows aio (read thread)
I/O thread 6 state: wait Windows aio (write thread)
I/O thread 7 state: wait Windows aio (write thread)
I/O thread 8 state: wait Windows aio (write thread)
I/O thread 9 state: wait Windows aio (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
 ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
1025 OS file reads, 545 OS file writes, 11 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
 insert 0, delete mark 0, delete 0
discarded operations:
 insert 0, delete mark 0, delete 0
Hash table size 2267, node heap has 0 buffer(s)
Hash table size 2267, node heap has 1 buffer(s)
Hash table size 2267, node heap has 3 buffer(s)
Hash table size 2267, node heap has 1 buffer(s)
Hash table size 2267, node heap has 0 buffer(s)
Hash table size 2267, node heap has 0 buffer(s)
Hash table size 2267, node heap has 0 buffer(s)
Hash table size 2267, node heap has 0 buffer(s)
0.00 hash searches/s, 0.29 non-hash searches/s
---
LOG
---
Log sequence number          24309079
Log buffer assigned up to    24309079
Log buffer completed up to   24309079
Log written up to            24309079
Log flushed up to            24309079
Added dirty pages up to      24309079
Pages flushed up to          24309079
Last checkpoint at           24309079
388 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 8585216
Dictionary memory allocated 361173
Buffer pool size   512
Free buffers       251
Database pages     256
Old database pages 0
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 1002, created 132, written 144
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 256, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
0 read views open inside InnoDB
Process ID = 3260, Main thread ID = 000000000000106C , state = sleeping
Number of rows inserted 0, updated 313, deleted 0, read 4534
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.14 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
                                                                                      |
+--------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql>

위 출력 결과에는 스레드와 I/O 관련된 모든 세부 정보가 포함되어 있습니다. 특히 TRANSACTIONS 섹션에서는 현재 실행 중인 트랜잭션 목록과 각 트랜잭션이 보유한 행 잠금(row lock) 정보를 확인할 수 있으므로, 어떤 트랜잭션이 잠금 대기 시간 초과의 원인인지 추적하는 데 유용합니다.

추가 디버깅 방법

SHOW ENGINE INNODB STATUS 외에도 아래 방법들을 함께 활용하면 더욱 정확한 원인 분석이 가능합니다.

  • information_schema.INNODB_TRX 조회: 현재 실행 중인 InnoDB 트랜잭션 목록과 트랜잭션 시작 시간, 실행 중인 SQL 문 등을 확인할 수 있습니다.
  • innodb_lock_wait_timeout 조정: 기본값은 50초이며, SET GLOBAL innodb_lock_wait_timeout = 100;과 같이 전역 또는 세션 단위로 변경할 수 있습니다.
  • 장기 실행 트랜잭션 종료: 불필요하게 오랫동안 잠금을 점유 중인 트랜잭션을 찾았다면 KILL <프로세스 ID>; 명령으로 종료하여 잠금을 해제할 수 있습니다.