我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MySQL中如何使用MDL字典锁

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MySQL中如何使用MDL字典锁

这篇文章将为大家详细讲解有关MySQL中如何使用MDL字典锁,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

  • 什么是MDL

         MDL,Meta Data lock,元数据锁,一般称为字典锁。字典锁与数据锁相对应。字典锁是为了保护数据对象被改变,一般是一些DDL会对字典对象改变,如两个TX,TX1先查询表,然后TX2试图DROP,字典锁就会lock住TX2,知道TX1结束(提交或回滚)。数据锁是保护表中的数据,如两个TX同时更新一行时,先得到row lock的TX会先执行,后者只能等待。

  • MDL的设计目标

字典锁在设计的时候是为了数据库对象的元数据。到达以下3个目的。

1. 提供对并发访问内存中字典对象缓存(table definatin cache,TDC)的保护。这是系统的内部要求。

2. 确保DML的并发性。如TX1对表T1查询,TX2同是对表T1插入。

3. 确保一些操作的互斥性,如DML与大部分DDL(ALTER TABLE除外)的互斥性。如TX1对表T1执行插入,TX2执行DROP TABLE,这两种操作是不允许并发的,故需要将表对象保护起来,这样可以保证binlog逻辑的正确性。(貌似之前的版本存在字典锁是语句级的,导致binlog不合逻辑的bug。)

  • 支持的锁类型

        数据库理论中的基本锁类型是S、X,意向锁IS、IX是为了层次上锁而引入的。比如要修改表中的数据,可能先对表上一个表级IX锁,然后再对修改的数据上一个行级X锁,这样就可以保证其他试图修改表定义的事物因为获取不到表级的X锁而等待。

        MySQL中将字典锁的类型根据不同语句的功能,进一步细分,细分的依据是对字典的操作和对数据的操作。细分的好处是能在一定程度上提高并发效率,因为如果只定义X和S两种锁,必然导致兼容性矩阵的局限性。MySQL不遗余力的定义了如下的锁类型。

          可以看到MySQL在ALTER TABLE的时候还是允许其他事务进行读表操作的。需要注意的是读操作的事物需要在ALTER TABLE获取MDL_SHARED_NO_WRITE锁之后,否则无法并发。这种应用场景应该是对一个较大的表进行ALTER时,其他事物仍然可以读,并发性得到了提高。

  • 锁的兼容性

          锁的兼容性就是我们经常看到的那些兼容性矩阵,X和S必然互斥,S和S兼容。MySQL根据锁的类型我们也可以知道其兼容矩阵如下:

         1代表兼容,0代表不兼容。你可能发现X和IX竟然兼容,没错,其实这里的IX已经不是传统意义上的IX,这个IX是用在范围锁上,所以和X锁不互斥。

  • 数据结构

涉及到的和锁相关的数据结构主要是如下几个:

MDL_context:字典锁上下文。包含一个事物所有的字典锁请求。

MDL_request:字典锁请求。包含对某个对象的某种锁的请求。

MDL_ticket:字典锁排队。MDL_request就是为了获取一个ticket。

MDL_lock:锁资源。一个对象全局唯一。可以允许多个可以并发的事物同时获得。

涉及到的文件主要是sql/mdl.cc

锁资源

         锁资源在系统中是共享的,即全局的,存放在static MDL_map mdl_locks;的hash链表中,对于中的一个对象,其hashkey必然是唯一的,对应一个锁资源。多个事务同时对一张表操作时,申请的lock也是同一个内存对象。获取mdl_locks中的lock需要通过全局互斥量保护起来_mutex_lock(&m_mutex); m_mutex是MDL_map的成员。

上锁流程

        一个会话连接在实现中对应一个THD实体,一个THD对应一个MDL_CONTEXT,表示需要的mdl锁资源,一个MDL_CONTEXT中包含多个MDL_REQUEST,一个MDL_REQUEST即是对一个对象的某种类型的lock请求。每个mdl_request上有一个ticket对象,ticket中包含lock。

上锁的也就是根据MDL_REQUEST进行上锁。

Acquire_lock:

    if (mdl_request contains the needed ticket )

    return ticket;

    End if;

    Create a ticket;

    If (!find lock in lock_sys)

    Create a lock;

    End if

    If (lock can be granted to mdl_request)

    Set lock to ticket;

    Set ticket to mdl_request;

    Else

    Wait for lock

End if

          稍微解释下,首先是在mdl_request本身去查看有没有相等的或者stronger的ticket,如果存在,则直接使用。否则创建一个ticket,查找上锁对象对应的lock,没有则创建。检查lock是否可以被赋给本事务,如果可以直接返回,否则等待这个lock;

锁等待与唤醒

        字典对象的锁等待是发生在两个事物对同一对象上不兼容的锁导致的。当然,由于lock的唯一性,先到先得,后到的只能等待。

         如何判断一个lock是否可以grant给一个TX?这需要结合lock结构来看了,lock上有两个成员,grant和wait,grant代表此lock允许的事物都上了哪些锁,wait表示等待的事务需要上哪些锁。其判断一个事物是否可以grant的逻辑如下:

If(compatible(lock.grant, tx.locktype))

    If (compatible(lock.wait, tx.locktype))

    return can_grant;

    End if

End if

         即首先判断grant中的锁类型和当前事务是否兼容,然后判断wait中的锁类型和当前事务是否兼容。细心的话,会想到,wait中的锁类型是不需要和当前事务进行兼容性比较的,这是不是说这个比较是多余的了?其实也不是,因为wait的兼容性矩阵和上面的矩阵是不一样的,wait的兼容性矩阵感觉是在DDL等待的情况下,防止DML继续进来(wait矩阵就不写出来了,大家可以去代码里看下)。

比如:

TX1                                                      TX2                                                       TX3

SELECT T1

                                                             DROP  T1

                                                                                                                              SELECT T1

        这时候TX2会阻塞,TX3也会阻塞,被TX2阻塞,也就是说被wait的事件阻塞了,这样可能就是为了保证在DDL等待时,禁止再做DML了,因为在DDL面前,DML显得确实不是那么重要了。

          如何唤醒被等待的事务呢?比如唤醒TX2,当TX1结束时,会调用release_all_locks_for_name,对被锁住的事务进行唤醒,具体操作封装在reschedule_waiters函数中,重置等待时间的标记位进行唤醒,重点代码如下:

if (can_grant_lock(ticket->get_type(), ticket->get_ctx()))

    {

      if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED))

      {

       

        m_waiting.remove_ticket(ticket);

        m_granted.add_ticket(ticket);

    }

关于MySQL中如何使用MDL字典锁就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MySQL中如何使用MDL字典锁

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python中字典如何使用

这期内容当中小编将会给大家带来有关Python中字典如何使用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Python字典应用方式1)get(key,default=None) 返回键值key对应的值;如
2023-06-17

mysql锁如何使用

mysql 提供多种锁类型,包括表锁和行锁(共享锁和排他锁)。表锁用于对整个表进行修改,而行锁用于并发事务中防止冲突。mysql 自动获取和释放锁,采用等待-回滚机制处理锁定冲突。优化锁的使用包括优先使用行锁、使用乐观锁、使用事务管理锁以及
mysql锁如何使用
2024-06-15

在Python字典中如何使用源文件

在Python字典中如何使用源文件,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Python字典现已成为一种广泛应用的计算机语言,但是很多人对Python字典的相关应用方案还是
2023-06-17

Python中的集合和字典如何使用

这篇文章主要讲解了“Python中的集合和字典如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python中的集合和字典如何使用”吧!1 集合集合可以使用大括号({})或者set()函
2023-06-29

如何使用python合并字典

今天就跟大家聊聊有关如何使用python合并字典,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。python有哪些常用库python常用的库:1.requesuts;2.scrapy;
2023-06-14

mysql如何使用表锁

这篇文章给大家分享的是有关mysql如何使用表锁的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1、全表更新。事务需要更新大部分或全部数据,且表又比较大。若使用行锁,会导致事务执行效率低,从而可能造成其他事务长时间
2023-06-15

python如何使用字典dict统计

这篇文章主要介绍python如何使用字典dict统计,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!使用字典 dict 统计循环遍历出一个可迭代对象的元素,如果字典中没有该元素,那么就让该元素作为字典的键,并将该键赋值
2023-06-27

Python字典和集合如何使用

这篇文章主要介绍“Python字典和集合如何使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python字典和集合如何使用”文章能帮助大家解决问题。字典简介Python 中字典和集合也是非常相近的
2023-07-04

如何使用Python实现字典合并

这篇文章给大家分享的是有关如何使用Python实现字典合并的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1、用for循环把一个字典合并到另一个字典把a字典合并到b字典中,相当于用for循环遍历a字典,然后取出a字
2023-06-29

python如何使用字典来存储switch

这篇文章主要为大家展示了“python如何使用字典来存储switch”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python如何使用字典来存储switch”这篇文章吧。使用字典来存储 swit
2023-06-27

python如何使用Get()方法检索字典中的值

这篇文章主要介绍python如何使用Get()方法检索字典中的值,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!用Get()方法检索字典中的值通常情况下,可以在方括号中指定键来检索键的值。但是,当键不在字典中时,就可能
2023-06-27

编程热搜

目录