DBAtlas · Atlas de operações de banco de dados

Diagnosticar 'Waiting for table metadata lock' e encontrar o verdadeiro bloqueador

MySQLDesempenho

Comando

-- 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;

O que faz

Mostra em qual metadata lock de qual sessão um DDL como ALTER / TRUNCATE / RENAME está esperando, e as consultas enfileiradas atrás do DDL. O bloqueador geralmente é uma sessão em Sleep que leu a tabela e nunca fechou sua transação.

Quando usar

Quando, após o início de um ALTER, todas as consultas naquela tabela se acumulam em 'Waiting for table metadata lock'.

Atenção

Um DDL em espera também bloqueia os SELECTs que chegam depois dele; decida rápido durante o incidente: faça KILL na sessão bloqueadora ou cancele o ALTER (KILL QUERY). O PROCESSLIST_INFO do bloqueador pode ser NULL (ocioso); use performance_schema.events_statements_history ou sys.session.last_statement para ver seu último statement. Prevenção: execute DDL após SET SESSION lock_wait_timeout = 5 para que o ALTER desista rápido, e evite transações abertas longas na aplicação.

Abrir no DBAtlas →

Relacionados