DBAtlas · 데이터베이스 운영 아틀라스

'Waiting for table metadata lock' 진단 및 실제 블로커 찾기

MySQL성능

명령어

-- Waiter -> blocker pairs; filter out the ALTER's own SHARED_UPGRADABLE entry
SELECT object_schema, object_name, waiting_pid, LEFT(waiting_query, 60) AS waiting_query,
       waiting_lock_type, blocking_pid, blocking_lock_type, sql_kill_blocking_connection
FROM sys.schema_table_lock_waits
WHERE blocking_lock_type <> 'SHARED_UPGRADABLE';

-- All MDLs on the table, owner age and open transaction
SELECT ml.OBJECT_SCHEMA, ml.OBJECT_NAME, ml.LOCK_TYPE, ml.LOCK_DURATION, ml.LOCK_STATUS,
       t.PROCESSLIST_ID AS conn_id, t.PROCESSLIST_COMMAND AS command, t.PROCESSLIST_TIME AS sec,
       LEFT(t.PROCESSLIST_INFO, 60) AS query, trx.trx_started
FROM performance_schema.metadata_locks ml
JOIN performance_schema.threads t ON t.THREAD_ID = ml.OWNER_THREAD_ID
LEFT JOIN information_schema.INNODB_TRX trx ON trx.trx_mysql_thread_id = t.PROCESSLIST_ID
WHERE ml.OBJECT_TYPE = 'TABLE' AND ml.OBJECT_SCHEMA NOT IN ('performance_schema', 'mysql')
ORDER BY ml.OBJECT_NAME, ml.LOCK_STATUS DESC;

하는 일

ALTER / TRUNCATE / RENAME 같은 DDL이 어느 세션의 메타데이터 락을 기다리는지, 그리고 DDL 뒤에 대기 중인 쿼리를 보여 준다. 블로커는 보통 테이블을 읽고 트랜잭션을 닫지 않은 Sleep 상태 세션이다.

사용 시점

ALTER 시작 후 해당 테이블의 모든 쿼리가 'Waiting for table metadata lock'에 쌓일 때.

주의

대기 중인 DDL은 그 뒤에 도착한 SELECT도 막는다. 장애 중에는 빠르게 결정한다: 블로킹 세션을 KILL하거나 ALTER를 취소(KILL QUERY)한다. 블로커의 PROCESSLIST_INFO는 NULL(유휴)일 수 있으므로 마지막 문장은 performance_schema.events_statements_history 또는 sys.session.last_statement로 확인한다. 예방: ALTER가 빨리 포기하도록 SET SESSION lock_wait_timeout = 5 이후 DDL을 실행하고, 애플리케이션에서 긴 열린 트랜잭션을 피한다.

DBAtlas에서 열기 →

관련 항목