'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을 실행하고, 애플리케이션에서 긴 열린 트랜잭션을 피한다.