一 查看元数据锁
1.1 前提条件
1、需要确保下面这个sql查询出来的ENABLED值为YES
select ENABLED from performance_schema.setup_instruments WHERE NAME = 'wait/lock/metadata/sql/mdl';
如果为NO,则需要先将其开启:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES'WHERE NAME = 'wait/lock/metadata/sql/mdl';
如果要永久生效,需要在配置文件中加入如下内容:
performance-schema-instrument='wait/lock/metadata/sql/mdl=ON'
2、需要确保events_statements_history的ENABLED值为YES
select ENABLED from performance_schema.setup_consumers
where name='events_statements_history';
如果为NO,则需要先将其开启:
UPDATE performance_schema.setup_consumers set ENABLED='YES' where name='events_statements_history';
1.2 查询元数据锁sql
#该sql在Mysql 5.7及8.0版本都试用
select *
from
(
SELECT locked_schema,
locked_table,
locked_type,
waiting_processlist_id,
waiting_processlist_user,
waiting_processlist_host,
waiting_thread_id,
waiting_time,
waiting_query,
waiting_state,
blocking_processlist_id,
blocking_processlist_user,
blocking_processlist_host,
granted_thread_id as blocking_thread_id,
blocking_time,
sql_text AS blocking_query,
blocking_command,
blocking_state,
kill_blocking_id
FROM
(
SELECT
b.OWNER_THREAD_ID AS granted_thread_id,
a.OWNER_THREAD_ID as waiting_thread_id,
a.OBJECT_SCHEMA AS locked_schema,
a.OBJECT_NAME AS locked_table,
'Metadata Lock' AS locked_type,
c.PROCESSLIST_ID AS waiting_processlist_id,
c.PROCESSLIST_user AS waiting_processlist_user,
c.PROCESSLIST_host AS waiting_processlist_host,
c.PROCESSLIST_TIME AS waiting_time,
c.PROCESSLIST_INFO AS waiting_query,
c.PROCESSLIST_STATE AS waiting_state,
d.PROCESSLIST_ID AS blocking_processlist_id,
d.PROCESSLIST_user AS blocking_processlist_user,
d.PROCESSLIST_host AS blocking_processlist_host,
d.PROCESSLIST_TIME AS blocking_time,
d.PROCESSLIST_INFO AS blocking_query,
d.PROCESSLIST_COMMAND as blocking_command,
d.PROCESSLIST_STATE as blocking_state,
CONCAT('KILL ', d.PROCESSLIST_ID,';') AS kill_blocking_id
FROM performance_schema.metadata_locks a
JOIN performance_schema.metadata_locks b ON a.OBJECT_SCHEMA = b.OBJECT_SCHEMA
AND a.OBJECT_NAME = b.OBJECT_NAME
AND a.lock_status = 'PENDING'
AND b.lock_status = 'GRANTED'
AND a.OWNER_THREAD_ID <> b.OWNER_THREAD_ID
#AND a.lock_type = 'EXCLUSIVE'
JOIN performance_schema.threads c ON a.OWNER_THREAD_ID = c.THREAD_ID
JOIN performance_schema.threads d ON b.OWNER_THREAD_ID = d.THREAD_ID
) t1,
(
SELECT thread_id, sql_text
FROM
performance_schema.events_statements_history
) t2
WHERE t1.granted_thread_id = t2.thread_id
) t3
where t3.blocking_query like concat('%',locked_table,'%');
如果blocking_query为空,则可能这个sql已经在历史会话里不存在了(每个会话默认存10条历史sql记录),需要酌情调整performance_schema_events_statements_history_size变量的大小
二 查看长时间运行的休眠(未提交)事务及相关锁等待信息
有时候有的同事会手动开启一个事务,执行完一些sql,但没提交该事务,事务处于sleep休眠状态,该事务会阻塞其他事务执行,这时需要找出这些正在运行的但是状态为休眠状态的事务。
2.1 查执行时间超过5分钟的休眠的事务
#Mysql 5.7,8.0版本都通用
SELECT p.id,d.thread_id,t.trx_id,p.user,p.host,p.db,t.trx_started,p.time,p.state,t.trx_state,p.command,p.info,t.trx_query,l.sql_text
FROM information_schema.INNODB_TRX t
INNER JOIN information_schema.PROCESSLIST p ON t.trx_mysql_thread_id=p.id
INNER JOIN performance_schema.threads d on d.processlist_id=p.id
INNER JOIN
(
select thread_id,group_concat(sql_text SEPARATOR ';') as sql_text from
performance_schema.events_statements_history
where event_name not in('statement/sql/set_option','statement/sql/show_status')
and sql_text not like '%INFORMATION_SCHEMA%'
group by thread_id
) l
on l.thread_id=d.thread_id
WHERE t.trx_state='RUNNING'
AND p.COMMAND='Sleep'
AND p.TIME>300
ORDER BY t.trx_started ASC
2.2 查询相关具体阻塞信息(谁阻塞了谁)
2.2.1 Mysql 5.7版本
select waiting_id,waiting_trx_id,waiting_user,waiting_host,waiting_query,db,blocking_id,blocking_command,blockting_trx_id,blocking_host,blocking_user,blocking_processlist_state,blocking_trx_started,blocking_trx_runtime,blocking_trx_state,blocking_id_current_query,blocking_sql_text,kill_blocking_id
from
(
select p1.id as 'waiting_id',w.REQUESTING_TRX_ID AS 'waiting_trx_id',p1.user as 'waiting_user',p1.host as 'waiting_host',p1.info as 'waiting_query',p1.db,p2.id as 'blocking_id',w.BLOCKING_TRX_ID as 'blockting_trx_id',p2.user as 'blocking_user',p2.host as 'blocking_host',p2.info as 'blocking_id_current_query',concat('kill ',p2.id,';') as 'kill_blocking_id'
from
information_schema.innodb_lock_waits w
inner join information_schema.innodb_trx t1 on w.REQUESTING_TRX_ID=t1.trx_id
inner join information_schema.innodb_trx t2 on w.BLOCKING_TRX_ID=t2.trx_id
inner join information_schema.PROCESSLIST p1 on t1.trx_mysql_thread_id=p1.id
inner join information_schema.PROCESSLIST p2 on t2.trx_mysql_thread_id=p2.id
) j1
JOIN
(
SELECT p.command as 'blocking_command',p.state as 'blocking_processlist_state',t.trx_id,t.trx_started as 'blocking_trx_started',p.time as 'blocking_trx_runtime',t.trx_state as 'blocking_trx_state',l.sql_text as 'blocking_sql_text'
FROM information_schema.INNODB_TRX t
INNER JOIN information_schema.PROCESSLIST p ON t.trx_mysql_thread_id=p.id
INNER JOIN performance_schema.threads d on d.processlist_id=p.id
INNER JOIN
(
select thread_id,group_concat(sql_text SEPARATOR ';') as sql_text from
performance_schema.events_statements_history
where event_name not in('statement/sql/set_option','statement/sql/show_status')
and sql_text not like '%INFORMATION_SCHEMA%'
group by thread_id
) l
on l.thread_id=d.thread_id
WHERE t.trx_state='RUNNING'
AND p.command='Sleep'
AND p.TIME>300
ORDER BY t.trx_started ASC
) j2 on j1.blockting_trx_id=j2.trx_id;
2.2.2 Mysql 8.0版本
select waiting_id,waiting_thread_id,waiting_trx_id,waiting_user,waiting_host,waiting_query,db,blocking_id,blocking_command,BLOCKING_THREAD_ID,blockting_trx_id,blocking_host,blocking_user,blocking_processlist_state,blocking_trx_started,blocking_trx_runtime,blocking_trx_state,blocking_id_current_query,blocking_sql_text,kill_blocking_id
from
(
select p1.id as 'waiting_id',w.REQUESTING_THREAD_ID as 'waiting_thread_id',w.REQUESTING_ENGINE_TRANSACTION_ID AS 'waiting_trx_id',p1.user as 'waiting_user',p1.host as 'waiting_host',p1.info as 'waiting_query',p1.db,p2.id as 'blocking_id',w.BLOCKING_THREAD_ID,w.BLOCKING_ENGINE_TRANSACTION_ID as 'blockting_trx_id',p2.user as 'blocking_user',p2.host as 'blocking_host',p2.info as 'blocking_id_current_query',concat('kill ',p2.id,';') as 'kill_blocking_id'
from
performance_schema.data_lock_waits w
inner join performance_schema.threads t1 on w.REQUESTING_THREAD_ID=t1.THREAD_ID
inner join performance_schema.threads t2 on w.BLOCKING_THREAD_ID=t2.THREAD_ID
inner join information_schema.PROCESSLIST p1 on t1.PROCESSLIST_ID=p1.id
inner join information_schema.PROCESSLIST p2 on t2.PROCESSLIST_ID=p2.id
) j1
JOIN
(
SELECT p.command as 'blocking_command',p.state as 'blocking_processlist_state',t.trx_id,t.trx_started as 'blocking_trx_started',p.time as 'blocking_trx_runtime',t.trx_state as 'blocking_trx_state',l.sql_text as 'blocking_sql_text'
FROM information_schema.INNODB_TRX t
INNER JOIN information_schema.PROCESSLIST p ON t.trx_mysql_thread_id=p.id
INNER JOIN performance_schema.threads d on d.processlist_id=p.id
INNER JOIN
(
select thread_id,group_concat(sql_text SEPARATOR ';') as sql_text from
performance_schema.events_statements_history
where event_name not in('statement/sql/set_option','statement/sql/show_status')
and sql_text not like '%INFORMATION_SCHEMA%'
group by thread_id
) l
on l.thread_id=d.thread_id
WHERE t.trx_state='RUNNING'
AND p.command='Sleep'
AND p.TIME>300
ORDER BY t.trx_started ASC
) j2 on j1.blockting_trx_id=j2.trx_id
三 查看当前行锁(包括休眠事务)
3.1 Mysql 5.7版本
select waiting_id,waiting_trx_id,waiting_user,waiting_host,waiting_query,db,blocking_id,blocking_command,blockting_trx_id,blocking_host,blocking_user,blocking_processlist_state,blocking_trx_started,blocking_trx_runtime,blocking_trx_state,blocking_id_current_query,blocking_sql_text,kill_blocking_id
from
(
select p1.id as 'waiting_id',w.REQUESTING_TRX_ID AS 'waiting_trx_id',p1.user as 'waiting_user',p1.host as 'waiting_host',p1.info as 'waiting_query',p1.db,p2.id as 'blocking_id',w.BLOCKING_TRX_ID as 'blockting_trx_id',p2.user as 'blocking_user',p2.host as 'blocking_host',p2.info as 'blocking_id_current_query',concat('kill ',p2.id,';') as 'kill_blocking_id'
from
information_schema.innodb_lock_waits w
inner join information_schema.innodb_trx t1 on w.REQUESTING_TRX_ID=t1.trx_id
inner join information_schema.innodb_trx t2 on w.BLOCKING_TRX_ID=t2.trx_id
inner join information_schema.PROCESSLIST p1 on t1.trx_mysql_thread_id=p1.id
inner join information_schema.PROCESSLIST p2 on t2.trx_mysql_thread_id=p2.id
) j1
JOIN
(
SELECT p.command as 'blocking_command',p.state as 'blocking_processlist_state',t.trx_id,t.trx_started as 'blocking_trx_started',p.time as 'blocking_trx_runtime',t.trx_state as 'blocking_trx_state',l.sql_text as 'blocking_sql_text'
FROM information_schema.INNODB_TRX t
INNER JOIN information_schema.PROCESSLIST p ON t.trx_mysql_thread_id=p.id
INNER JOIN performance_schema.threads d on d.processlist_id=p.id
INNER JOIN
(
select thread_id,group_concat(sql_text SEPARATOR ';') as sql_text from
performance_schema.events_statements_history
where event_name not in('statement/sql/set_option','statement/sql/show_status')
and sql_text not like '%INFORMATION_SCHEMA%'
group by thread_id
) l
on l.thread_id=d.thread_id
ORDER BY t.trx_started ASC
) j2 on j1.blockting_trx_id=j2.trx_id;
3.2 Mysql 8.0版本
select waiting_id,waiting_thread_id,waiting_trx_id,waiting_user,waiting_host,waiting_query,db,blocking_id,blocking_command,BLOCKING_THREAD_ID,blockting_trx_id,blocking_host,blocking_user,blocking_processlist_state,blocking_trx_started,blocking_trx_runtime,blocking_trx_state,blocking_id_current_query,blocking_sql_text,kill_blocking_id
from
(
select p1.id as 'waiting_id',w.REQUESTING_THREAD_ID as 'waiting_thread_id',w.REQUESTING_ENGINE_TRANSACTION_ID AS 'waiting_trx_id',p1.user as 'waiting_user',p1.host as 'waiting_host',p1.info as 'waiting_query',p1.db,p2.id as 'blocking_id',w.BLOCKING_THREAD_ID,w.BLOCKING_ENGINE_TRANSACTION_ID as 'blockting_trx_id',p2.user as 'blocking_user',p2.host as 'blocking_host',p2.info as 'blocking_id_current_query',concat('kill ',p2.id,';') as 'kill_blocking_id'
from
performance_schema.data_lock_waits w
inner join performance_schema.threads t1 on w.REQUESTING_THREAD_ID=t1.THREAD_ID
inner join performance_schema.threads t2 on w.BLOCKING_THREAD_ID=t2.THREAD_ID
inner join information_schema.PROCESSLIST p1 on t1.PROCESSLIST_ID=p1.id
inner join information_schema.PROCESSLIST p2 on t2.PROCESSLIST_ID=p2.id
) j1
JOIN
(
SELECT p.command as 'blocking_command',p.state as 'blocking_processlist_state',t.trx_id,t.trx_started as 'blocking_trx_started',p.time as 'blocking_trx_runtime',t.trx_state as 'blocking_trx_state',l.sql_text as 'blocking_sql_text'
FROM information_schema.INNODB_TRX t
INNER JOIN information_schema.PROCESSLIST p ON t.trx_mysql_thread_id=p.id
INNER JOIN performance_schema.threads d on d.processlist_id=p.id
INNER JOIN
(
select thread_id,group_concat(sql_text SEPARATOR ';') as sql_text from
performance_schema.events_statements_history
where event_name not in('statement/sql/set_option','statement/sql/show_status')
and sql_text not like '%INFORMATION_SCHEMA%'
group by thread_id
) l
on l.thread_id=d.thread_id
ORDER BY t.trx_started ASC
) j2 on j1.blockting_trx_id=j2.trx_id