百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

如何迅速并识别处理MDL锁阻塞问题

wptr33 2025-02-18 13:40 36 浏览

摘要:TaurusDB推出MDL锁视图功能,帮助用户迅速识别并处理MDL锁阻塞问题,从而有效减少对业务的负面影响,提升数据库管理效率。

本文分享自华为云社区《【华为云MySQL技术专栏】TaurusDB MDL锁视图-云社区-华为云》,作者:GaussDB 数据库。

一、背景

数据库中的元数据锁(MDL ,Metadata Lock),用来保护表元数据信息的一致性。用户对表进行读写操作或结构变更时,系统会添加不同类型的MDL锁。当客户业务设计不合理,有部分事务长时间持有MDL锁时,可能会阻塞其他会话获取相应的MDL锁。此时,用户使用执行‘SHOW PROCESSLIST’命令,通常会看到多个会话处于 “Waiting for metadata lock” 状态。但由于无法明确各个会话ID之间的关联,往往无法快速找到导致大量MDL锁等待的根源,使得用户不得不盲目地Kill大量可疑的会话,甚至直接重启实例来快速恢复业务,这种做法无疑增加了解决问题的成本,对业务产生较大影响。

因此,自社区MySQL 5.7版本之后,在PERFORMANCE_SCHEMA 库中新增了METADATA_LOCKS 表,用于记录系统中MDL锁的状态信息,但是需要客户启用 Performance Schema 性能分析监控插件。启用后,Performance Schema 会收集大量的性能数据,包括SQL语句执行情况和实例内的锁状态信息等,这会对 MySQL 实例的性能产生一定的负担,尤其在高并发的生产环境中,性能开销更为明显。

鉴于此,TaurusDB推出MDL锁视图功能,帮助用户迅速识别并处理MDL锁阻塞问题,从而有效减少对业务的负面影响,提升数据库管理效率。

二、MDL锁阻塞场景分析

我们以表1中的MDL锁阻塞案例来介绍MDL锁视图的使用场景


由于SESSION 3存在一个长事务未提交,会一直持有t2表的MDL_SHARED_READ(SR)类型锁。当SESSION 4对表t2执行TRUNCATE操作时,需要获取MDL-EXCLUSIVE(X)锁,但由于MDL锁类型和SR锁不兼容而被阻塞。

随后,SESSION 5的DML操作在添加SR类型的锁时,发现MDL锁等待队列中有比SR类型的锁优先级更高的X锁在等待,所以SESSION 5的SR锁请求也会处于等待状态,详细原因可参考《【华为云MySQL技术专栏】TaurusDB新特性解读:非阻塞DDL》。

用户发现DDL和DML操作都被阻塞后,执行SHOW PROCESSLIST查看原因。在SHOW PROCESSLIST的信息中,只能看到如图1中的结果:


  • SESSION 4执行TRUNCATE操作时,被其他SESSION持有的table metadata lock阻塞;
  • SESSION 5执行SELECT操作时,也同样被阻塞;
  • 无法确定哪个会话(2或3?)阻塞了SESSION 4和SESSION 5;

此时,如果业务盲目地去kill其他会话(2或3),可能会影响其他不相关的业务,从而加大问题处理的成本。在实际的生产业务中,可能有更多的会话,用户从成百上千的会话信息中几乎无法找到导致MDL锁等待的根源,只能盲目地Kill大量的会话或者重启实例来快速恢复。而且用户在事后也无法定位到根因,从源头杜绝此类问题的再次发生。刚好,TaurusDB的MDL锁视图功能在这个时候就可以发挥作用。

三、MDL锁视图介绍

TaurusDB的MDL锁视图以系统表的形式呈现,该表位于INFORMATION_SCHEMA库下,表名为METADATA_LOCK_INFO。其中每一行的信息表示一个会话持有或正在等待的MDL锁信息。

每个字段的具体含义,如表2所示:


此表的查询结果中,同一个会话可能持有多行MDL锁的相关信息。主要有以下几方面的原因:

1)当执行涉及多张表的连表查询时,会给每一个表添加MDL_SHARED_READ模式的MDL锁。

2)事务级别的MDL锁,只有在事务结束时才会释放。因此,当一个事务涉及多张表的DML操作时,这个会话会同时持有多个MDL锁,直到事务结束。

3)在DDL语句的执行过程中,需要添加多种类型的MDL锁。例如,在添加列的DDL语句中,可能会添加Backup lock,Global read lock,Schema metadata lock,Table metadata lock,并且在不同阶段对锁的模式进行升/降级。

四、MDL锁视图使用方法

针对表格1中的MDL锁阻塞场景,用户可以执行以下SQL语句:SELECT * FROM
INFORMATION_SCHEMA.METADATA_LOCK_INFO;

再结合SHOW PROCESSLIST的输出结果,快速定位到问题根因。

在图2元数据锁视图的结果信息中,我们应该从PENDING状态的会话开始入手。


根据MDL锁等待的TABLE_SCHEMA和TABLE_NAME信息,找到其他THREAD ID下,具有相同库名和表名且状态是GRANTED的MDL锁信息。这个THREAD ID即是造成锁等待的会话。

基于以上原理,我们可以看出:

  • 会话4在等待获取test库t2表的MDL_EXCLUSIVE模式的元数据锁;
  • 会话5在等待获取test库t2表的MDL_SHARED_READ模式的元数据锁;
  • 会话3持有test库t2表t2的MDL锁,该MDL锁为事务级别,只要session 3 的事务不提交,session 4和5便会一直阻塞。

所以,通过MDL锁视图,我们只需要在会话3中执行Rollback或者Commit,便可以让业务继续运行。虽然MDL锁视图可以帮助定位到导致大量MDL锁等待的根源,但是当会话较多时,表中很多不相关的MDL锁信息查看起来也会耗费大量时间,这里我们提供一个可以快速查找到阻塞会话的SQL。在发生问题时,只要执行一下这个语句,就可以迅速找到需要kill的会话。

SELECT f.processlist_id, p.Info AS sql_info
FROM (
    SELECT DISTINCT c.blocking_processlist_id AS processlist_id
    FROM (
        SELECT DISTINCT b.THREAD_ID AS blocking_processlist_id
        FROM information_schema.metadata_lock_info a
            JOIN information_schema.metadata_lock_info b
            ON a.TABLE_SCHEMA = b.TABLE_SCHEMA
                AND a.TABLE_NAME = b.TABLE_NAME
                AND a.lock_status = 'PENDING'
                AND b.lock_status = 'GRANTED'
                AND a.THREAD_ID <> b.THREAD_ID
    ) c
    WHERE c.blocking_processlist_id NOT IN (
        SELECT DISTINCT d.THREAD_ID AS blocked_processlist_id
        FROM information_schema.metadata_lock_info d
            JOIN information_schema.metadata_lock_info e
            ON d.TABLE_SCHEMA = e.TABLE_SCHEMA
                AND d.TABLE_NAME = e.TABLE_NAME
                AND d.lock_status = 'PENDING'
                AND e.lock_status = 'GRANTED'
                AND d.THREAD_ID <> e.THREAD_ID
    )
) f
    JOIN information_schema.processlist p ON processlist_id = p.Id;

五、原理解析

基于对《【华为云MySQL技术专栏】TaurusDB MDL实现机制解析》中MDL锁相关数据结构和MDL锁添加、释放流程的分析,TaurusDB在INFORMATION_SCHEMA库下添加了MDL锁视图。

在TaurusDB的内部架构中,每一个用户连接有一个THD(Thread Handler,线程处理器)对象,这些THD对象统一由Global_THD_manager结构体进行管理。如图3所示,每个THD对象关联了一个MDL_context实例,这个实例提供了线程级的MDL锁操作接口,包括申请、释放MDL锁以及锁的升降级。


其中,THD中的MDL_context也有两个变量m_ticket_store和m_waiting_for用于维护会话持有和等待的MDL锁的信息。

  1. m_ticket_store: 用来存储当前线程获取的所有MDL_ticket。为了提升搜索效率,根据MDL锁的持续时间(语句执行时间段,事务执行时间段和显示指定时间段)将其划分为三个链表,在需要获取MDL锁前,会先在这些链表内查询是否已经获取到了相同的或这是更强类型的MDL锁,如果搜索不到继续获取MDL锁。

2. m_waiting_for:用来存储当前线程正在等待的MDL锁,一个线程同一时刻只能等待一种类型的MDL锁。


每一个链表中的MDL_ticket对象是每个线程已经获取到的MDL锁或者是要请求的MDL锁的详细信息,其结构体内包含MDL锁的模式(enum_mdl_type)、MDL锁的持续时间(enum_mdl_duration)和MDL锁对象(MDL_lock)。其中,MDL_lock由MDL_key唯一标识。MDL_key是一个三元组,由命名空间(enum_mdl_namespace)、库名和对象名组成。

因此,在用户查询MDL锁视图时,实现流程如图4所示,只需要遍历所有会话THD的MDL_context对象,根据其m_ticket_store链表中的每一个MDL_ticket对象构造出处于GRANTED状态的MDL锁信息。同理,通过m_waiting_for对象获取到处于PENDING状态的MDL锁信息。最后,将结果集返回给客户端展示即可。


其中,
i_s_metadata_lock_info_fill_table和List_THD_MDL_tickets为核心函数,用来实现遍历Global_THD_manager中的THD并从其MDL_context中构造当前会话的持有和等待的MDL锁信息。

i_s_metadata_lock_info_fill_table() {
    //对系统中每一个THD执行List_THD_MDL_tickets函数找到持有和等待的MDL锁
    Global_THD_manager::get_instance()->do_for_all_thd_copy(List_THD_MDL_tickets)
}

List_THD_MDL_tickets() {
    // 获取当前THD的MDL_context:
    MDL_context &mdl_ctx = inspect_thd->mdl_context;
    // 获取当前THD持有的MDL锁 
    const MDL_ticket_store &m_ticket_store = mdl_ctx.get_mdl_ticket_store();
    // 遍历每个m_ticket_store的三个作用范围内的MDL_ticket 
    for (int i = 0; i < MDL_DURATION_END; i++) {
      MDL_ticket_store::List_iterator it = m_ticket_store.list_iterator(duration);
      lock_extras.duration = duration;
      while ((ticket = it++)) {
        enum_mdl_duration duration = (enum_mdl_duration)(i);
        // 根据MDL_ticket中的信息填充到MDL锁视图中
        fill_row_callback(ticket, &lock_extras, args); 
      }
    }
    // 获取当前THD等待的MDL锁
    ticket = dynamic_cast(mdl_ctx.get_m_waiting_for());
    
    if (ticket != nullptr) {
      // 填充MDL锁的额外信息,PENDING状态和作用范围 
      lock_extras.lock_status = MDL_ticket::PENDING;
      lock_extras.duration = ticket->get_duration();
      // 根据MDL_ticket中的信息填充到MDL锁视图中
      fill_row_callback(ticket, &lock_extras, args);
    }
}

六、总结

TaurusDB的MDL锁视图
INFORMATION_SCHEMA.METADATA_LOCK_INFO,可以在不开启Performance Schema性能监控插件时,获取到实例系统中所有MDL锁的持有和等待状态。熟练的使用MDL锁视图,可以帮助用户快速地定位和分析导致大量 MDL 锁等待的根本原因,还能够根据分析结果进行迅速有效的处理,解决MDL长时间锁等待问题,并且不会因为依赖Performance Schema性能监控插件而对系统性能产生任何影响。

关注“GaussDB数据库”公众号,了解更多动态


点击关注,第一时间了解华为云新鲜技术~

华为云博客_大数据博客_AI博客_云计算博客_开发者中心-华为云

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...