vlambda博客
学习文章列表

MYSQL 8 从锁开始 监控你的锁,死锁,死锁的详细信息

MYSQL 中有一个重要的特性就是锁,如何认识到锁的概念对于使用MYSQL有着重要的意义,针对与锁的认识,以及发现我们需要通过MYSQL本身的performance_schema  中的表来了解,不熟悉这一个系列的同学可以去从之前的performance_schema 系列里面去了解performance_schema的日常使用。MYSQL的锁可以从 metadata 和 表锁开始。


下面的这个查询就对

select ss.thd_id,ss.conn_id,ss.user,ss.statement_latency,ss.lock_latency,ss.full_scan,
ss.current_memory,ss.trx_autocommit,ss.program_name,ml.object_name,ml.object_schema,
ml.lock_type,ml.lock_status,ss.current_statement
from performance_schema.metadata_locks as ml
left join sys.session as  ss on ml.owner_thread_id = ss.thd_id
where ml.object_type = 'table' and ml.object_name in  ('session');


MYSQL 8 从锁开始 监控你的锁,死锁,死锁的详细信息


上面的查询可以获得当前查询中的查询语句中正在获得的锁的形式以及内存消耗等。

下面的语句可以从performance_schema 中获得当前的查询中因为锁而正在锁定中的语句中所需的表,分为正在等待的访问的线程和正在阻挡这个线程运作的线程,当然可以稍微的在变化一下,就可以获得两个操作的语句,这里就不在网下扩展了。

SELECT OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME,
w.OWNER_THREAD_ID AS WAITING_THREAD_ID,
b.OWNER_THREAD_ID AS BLOCKING_THREAD_ID
FROM performance_schema.metadata_locks w
INNER JOIN performance_schema.metadata_locks b
USING (OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME)
WHERE w.LOCK_STATUS = 'PENDING'
AND b.LOCK_STATUS = 'GRANTED';
SELECT OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME,
w.OWNER_THREAD_ID AS WAITING_THREAD_ID,
b.OWNER_THREAD_ID AS BLOCKING_THREAD_ID
FROM performance_schema.metadata_locks w
INNER JOIN performance_schema.metadata_locks b
USING (OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME)
WHERE w.LOCK_STATUS = 'PENDING'
AND b.LOCK_STATUS = 'GRANTED';


基于上面的查询,实际上我们可以获得数据库中你想查看的当前查询语句的锁的问题,以及当前如果有语句之间产生BLOCK 的成因在哪里。


那么除此以外,我们在MYSQL的操作中的死锁的问题,怎么分析在MYSQL8 中祭出了表

1 data_lock_waits

2 data_locks

两个表

查询当前表中是否有死锁或锁的block,需要从data_lock_waits中获取信息,我们模拟一个死锁的场景,下面可以直接通过data_lock_waits 来获取到当时的一个信息,这个信息就是被最后被KILL掉的那个查询的信息。

主要就是两个点

1   requesting_thread_id

2   blocking_thread_id


我们即添加一些东西,就可以直接展示出死锁当时的情况。


MYSQL 8 从锁开始 监控你的锁,死锁,死锁的详细信息


select  dlw.REQUESTING_ENGINE_LOCK_ID,ss.thd_id,ss.current_statement,ss.last_statement,'killed_statement'
from  performance_schema.data_lock_waits as dlw
left join sys.session as ss on ss.thd_id = REQUESTING_THREAD_ID
union all
select  dlw.REQUESTING_ENGINE_LOCK_ID,ss.thd_id,ss.current_statement,ss.last_statement,'kill_statement'
from  performance_schema.data_lock_waits as dlw
left join sys.session as ss on ss.thd_id = BLOCKING_THREAD_ID;


MYSQL 8 从锁开始 监控你的锁,死锁,死锁的详细信息


从截图上看我们可以在死锁发生的瞬间,执行这个语句,并抓到当时死锁时的一刻发生了什么并且将那个语句将那个语句killed 看的一清二楚。

当然如果对此还不满足的情况下,那么我们可以在通过 data_locks 进行更深度的分析。


select  dlw.REQUESTING_ENGINE_LOCK_ID,ss.thd_id,ss.current_statement,ss.last_statement,'killed_statement',dl.index_name,dl.lock_type,dl.lock_mode
from  performance_schema.data_lock_waits as dlw
left join sys.session as ss on ss.thd_id = REQUESTING_THREAD_ID
left join performance_schema.data_locks as dl on ss.thd_id = dl.thread_id
union all
select  dlw.REQUESTING_ENGINE_LOCK_ID,ss.thd_id,ss.current_statement,ss.last_statement,'kill_statement',dl.index_name,dl.lock_type,dl.lock_mode
from  performance_schema.data_lock_waits as dlw
left join sys.session as ss on ss.thd_id = BLOCKING_THREAD_ID
left join performance_schema.data_locks as dl on ss.thd_id = dl.thread_id;



从图中看到,我们在操作同一个表,并且我们在操作同一个记录,此时我们的死锁发证在行锁,在同一个行中发生了互斥,导致上面的93号的线程中的信息被KILLED 。

锁的信息标注了,产生的是X行锁。 


以上的查询对于我们的分析死锁,以及成因有着很大的帮助。