【澳门金沙vip】MySQL源码学习:MDL字典锁

 

什么是MDL

一、前言

– 什么是MDL

         MDL,Meta Data
lock,元数据锁,一般称为字典锁。字典锁与数据锁相对应。字典锁是为着珍重数量对象被改成,一般是局地DDL会对字典对象改换,如多个TX,TX1先查询表,然后TX2意欲DROP,字典锁就能够lock住TX2,知道TX1甘休(提交或回滚)。数据锁是敬重表中的数据,如七个TX同期立异一行时,先获得row
lock的TX会先进行,后者只可以等待。

MDL,Meta Data
lock,元数据锁,一般称为字典锁。字典锁与数据锁相对应。字典锁是为着保养数量对象被改成,一般是有些DDL会对字典对象更改,如三个TX,TX1先查询表,然后TX2精算DROP,字典锁就能够lock住TX2,知道TX1说尽提交或回滚)。数据锁是保护表中的数据,如五个TX同有的时候间更新一行时,先获得row
lock的TX会西施行,后者只可以等待。

MYSQL中MDL锁一向是贰个相比令人可比脑瓜疼的难题,大家谈到锁一般越发倾向于INNODB下层的gap
lock、next key lock、row lock等,因为它很好精晓,也很好观望,而对于MDL
LOCK却领会得不多,因为它事实上不佳观看,只有出现难题查看show
processlist勉强能够见到

– 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。)

MDL的设计目的

简言之的所谓的Waiting for table metadata lock之类的意况,其实MDL
LOCK是MYSQL上层三个极度复杂的子系统,有友好的死锁检查测试机制

– 援助的锁类型

       
数据库理论中的基本锁类型是S、X,意向锁IS、IX是为了等级次序上锁而引进的。举例要修改表中的数据,或然先对表上一个表级IX锁,然后再对修改的多寡上叁个行级X锁,这样就能够确认保障其余试图修改表定义的东西因为获取不到表级的X锁而等待。

       
MySQL少将字典锁的门类依照分化语句的功能,进一步细分,划分的依附是对字典的操作和对数码的操作。细分的补益是能在必然水平上巩固并发效能,因为只要只定义X和S二种锁,必然形成包容性矩阵的局限性。MySQL用尽全力的定义了如下的锁类型。

名称 意义

MDL_INTENTION_EXCLUSIVE

意向排他锁,只用于范围上锁

MDL_SHARED

共享锁,用于访问字典对象,而不访问数据。

MDL_SHARED_HIGH_PRIO

只访问字典对象(如DESC TABLE)

MDL_SHARED_READ

共享读锁,用于读取数据(如select)

MDL_SHARED_WRITE

共享写锁,用于修改数据(如update)

MDL_SHARED_NO_WRITE

共享非写锁,允许读取数据,阻塞其他TX修改数据(如alter table)

MDL_SHARED_NO_READ_WRITE

用于访问字典,读写数据

不允许其他TX读写数据

MDL_EXCLUSIVE

排他锁,可以修改字典和数据

          能够看来MySQL在ALTER
TABLE的时候照旧同意任何作业进行读表操作的。须要小心的是读操作的事物要求在ALTER
TABLE获取MDL_SHARED_NO_W安德拉ITE锁之后,不然不大概出现。这种应用场景应该是对二个相当大的表进行ALTEOdyssey时,其余东西还是能够读,并发性得到了压实。

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

(无向图?)而大家一般口中的是或不是锁表了实际上便是指的它,可知的它的基点和严重性,笔者也是基于自个儿的须要学习了某些(冰山一角),而从不力量阅读全体的代码,但是作者通过扩充四个TICKET的打字与印刷函数让语句的MDL
LOCK加锁流程全体打字与印刷出来方便学习研商,上面从局地基础说到接下来告诉我们修改了哪些东西,最终对各种MDL
TYPE进行测试和剖判,如若我们对基本概念和增添打字与印刷函数不感兴趣可径直仿照效法第五局地加锁测试,可是只要不打听基础知识可能看起来有一点困难。

– 锁的包容性

         
锁的包容性正是大家平日来看的那二个包容性矩阵,X和S必然互斥,S和S包容。MySQL依照锁的品种我们也能够精晓其协作矩阵如下:

  IX S SH SR SW SNW SNRW X
IX 1 1 1 1 1 1 1 1
S 1 1 1 1 1 1 1 0
SH 1 1 1 1 1 1 1 0
SR 1 1 1 1 1 1 0 0
SW 1 1 1 1 1 0 0 0
SNW 1 1 1 1 0 0 0 0
SNRW 1 1 1 0 0 0 0 0
X 1 0 0 0 0 0 0 0

        
1代表包容,0代表不包容。你可能发掘X和IX竟然特别,没有错,其实这里的IX已经不是守旧意义上的IX,这么些IX是用在界定锁上,所以和X锁不排斥。

  1. 提供对出现访问内部存款和储蓄器中字典对象缓存(table definatin
    cache,TDC)的掩护。那是系统的内部须求。

  2. 管教DML的并发性。如TX1对表T1询问,TX2同是对表T1插入。

  3. 有限支撑一些操作的互斥性,如DML与大许多DDL(ALTER
    TABLE除此而外)的互斥性。如TX1对表T1实施插入,TX2进行DROP
    TABLE,这两种操作是不允许出现的,故供给将表对象保险起来,那样可以有限接济binlog逻辑的科学。貌似以前的本子存在字典锁是语句级的,导致
    binlog不合逻辑的bug。)

碰巧近来遇到三回MDL
LOCK出现死锁的情景会在下篇小说中付出案例,这里只看理论

– 数据结构

论及到的和锁相关的数据结构首假若之类几个:

 

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须要通过全局互斥量尊崇起来mysql_mutex_lock(&m_mutex);
m_澳门金沙vip,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))

      {

        /*

          Satisfy the found request by updating lock structures.

          It is OK to do so even after waking up the waiter since any

          session which tries to get any information about the state of

          this lock has to acquire MDL_lock::m_rwlock first and thus,

          when manages to do so, already sees an updated state of the

          MDL_lock object.

        */

        m_waiting.remove_ticket(ticket);

        m_granted.add_ticket(ticket);

    }

 

 

     
今日把mdl系统总体上看了须臾间,对锁的伸手、等待以及提示有了初阶摸底。并发性的标题是最难调节和测试的,大家只要想做锁方面包车型客车实验,能够应用VS调节和测试中的结霜线程的功效,那样就足以确认保证出现意况调控完全根据你布署思路去显示。

踏着落叶,追寻着我的企盼。转发请注明出处

 

小编 心中无码

MDL,Meta Data lock,元数据锁,一般称为
字典锁
。字典锁与数码锁相对应。字典锁是为着维护数量对象被退换,一般是一些DDL会对…

补助的锁类型

—-处于档次:MYSQL SE翼虎VE汉兰达档次,实际上早在open_table函数中MDL
LOCK就起来获得了,能够说他是最早得到的LOCK结构

数据库理论中的基本锁类型是S、X,意向锁IS、IX是为了档案的次序上锁而引进的。举个例子要修改表中的数据,可能先对表上三个表级IX锁,然后再对修改的数额上二个行级X锁,那样就能够保险别的试图修改表定义的东西因为获取不到表级的X锁而等待。

—-最早获得阶段: THD::enter_stage: ‘Opening tables’

MySQL少校字典锁的品类依据不相同语句的法力,进一步细分,细分的依据是对字典的操作和对数码的操作。细分的好处是能在任天由命程度上升高并发成效,因为一旦只定义X和S三种锁,必然导致兼容性矩阵的局限性。MySQL用尽全力的概念了之类的锁类型。

调用栈帧

名称

意义

MDL_INTENTION_EXCLUSIVE

意向排他锁,只用于范围上锁

MDL_SHARED

共享锁,用于访问字典对象,而不访问数据。

MDL_SHARED_HIGH_PRIO

只访问字典对象如DESC TABLE)

MDL_SHARED_READ

共享读锁,用于读取数据如select)

MDL_SHARED_WRITE

共享写锁,用于修改数据如update)

MDL_SHARED_NO_WRITE

共享非写锁,允许读取数据,阻塞其他TX修改数据如alter table)

MDL_SHARED_NO_READ_WRITE

用于访问字典,读写数据

不允许其他TX读写数据

MDL_EXCLUSIVE

排他锁,可以修改字典和数据

#0 open_table_get_mdl_lock (thd=0x7fffd0000df0, ot_ctx=0x7fffec06fb00, 
  table_list=0x7fffd00067d8, flags=0, mdl_ticket=0x7fffec06f950)
  at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_base.cc:2789
#1 0x0000000001516e17 in open_table (thd=0x7fffd0000df0, 
  table_list=0x7fffd00067d8, ot_ctx=0x7fffec06fb00)
  at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_base.cc:3237

可以看到MySQL在ALTER
TABLE的时候照旧允许别的业务进行读表操作的。供给专注的是读操作的东西须要在ALTER
TABLE获取MDL_SHARED_NO_W途乐ITE锁之后,不然无法出现。这种利用场景应该是对多少个比较大的表进行ALTEOdyssey时,别的东西仍能读,并发性获得了抓牢。

—-死锁检验出错码:

锁的包容性

{ "ER_LOCK_DEADLOCK", 1213, "Deadlock found when trying to get lock; try restarting transaction" },
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

锁的包容性正是我们平时来看的那个包容性矩阵,X和S必然互斥,S和S包容。MySQL依照锁的门类大家也得以精通其同盟矩阵如下:

MDL LOCK的死锁抛错和INNODB死锁一模二样分歧的只是SHOW ENGINE INNODB
未有死锁音讯。

IX

S

SH

SR

SW

SNW

SNRW

X

IX

1

1

1

1

1

1

1

1

S

1

1

1

1

1

1

1

0

SH

1

1

1

1

1

1

1

0

SR

1

1

1

1

1

1

0

0

SW

1

1

1

1

1

0

0

0

SNW

1

1

1

1

0

0

0

0

SNRW

1

1

1

0

0

0

0

0

X

1

0

0

0

0

0

0

0

—-涉及代码:mdl.h mdl.cc

1意味包容,0代表不相称。你可能开采X和IX竟然异常,没有错,其实这里的IX已经不是守旧意义上的IX,那些IX是用在界定锁上,所以和X锁不排斥。

二、基础首要的数据结构(类)和定义

数据结构

1、MDL TYPE

论及到的和锁相关的数据结构首假诺之类几个:

MDL_INTENTION_EXCLUSIVE(IX)

MDL_context:字典锁上下文。包含多个东西有着的字典锁请求。

MDL_SHARED(S)

MDL_request:字典锁请求。包涵对某些对象的某种锁的呼吁。

MDL_SHARED_HIGH_PRIO(SH)

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

MDL_SHARED_READ(SR)

MDL_lock:锁财富。七个对象全局唯一。能够允许多少个能够出现的东西同一时候获得。

MDL_SHARED_WRITE(SW)

关系到的源码文件根本是sql/mdl.cc

MDL_SHARED_WRITE_LOW_PRIO(SWL)

锁资源

MDL_SHARED_UPGRADABLE(SU)

锁能源在系统中是共享的,即全局的,存放在static MDL_map
mdl_locks;的hash链表中,对于数据库中的叁个目的,其hashkey必然是独占鳌头的,对应三个锁能源。四个事情同不日常间对一张表操作时,申请的
lock也是同二个内部存款和储蓄器对象。获取mdl_locks中的lock须要经过全局互斥量拥戴起来
mysql_mutex_lock(&m_mutex); m_mutex是MDL_map的成员。

MDL_SHARED_READ_ONLY(SRO)

上锁流程

MDL_SHARED_NO_WRITE(SNW)

一个对话连接在贯彻中对应三个THD实体,多个THD对应二个MDL_CONTEXT,表示必要的mdl锁能源,二个MDL_CONTEXT中蕴藏两个MDL_REQUEST,一个MDL_REQUEST正是对四个目的的某体系型的lock请求。每一个mdl_request上有八个ticket对象,ticket中带有lock。

MDL_SHARED_NO_READ_WRITE(SNRW)

上锁的也正是依靠MDL_REQUEST举行上锁。

MDL_EXCLUSIVE(X)

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 

末尾会对各类TYPE进行详尽的测试,最后也会提交源码中解释

稍稍解释下,首先是在mdl_request自身去查看有未有非常的还是stronger的ticket,假使存在,则直接采纳。不然创制多个ticket,查找上锁对象对应的lock,未有则开创。检查lock是或不是能够被赋给本作业,假如得以一贯回到,不然等待这一个lock;

2、MDL NAMESPACE

锁等待与唤醒

在MDL中MDL_KEY按照NAMESPACE+DB+OBJECT_NAME的方法开始展览表示,所谓的namespace也不叫首要

字典对象的锁等待是爆发在多少个东西对同样对象上不协作的锁导致的。当然,由于lock的唯一性,先到先得,后到的只好等待。

下面是NAMESPACE的分类

如何判别一个lock是或不是足以grant给八个TX?那亟需整合lock结构来看了,lock上有三个成员,grant和wait,grant代表此
lock允许的东西都上了什么锁,wait表示等待的事情必要上什么锁。其剖断叁个东西是或不是足以grant的逻辑如下:

– GLOBAL is used for the global read lock.

If(compatible(lock.grant, tx.locktype))      If (compatible(lock.wait, tx.locktype))      return can_grant;      End if  End if 

– TABLESPACE is for tablespaces.

即首先判断grant中的锁类型和当下政工是不是合营,然后剖断wait中的锁类型和脚下工作是还是不是相配。细心的话,会想到,wait中的锁类型是无需和近日业务进行兼容性相比较的,那是还是不是说那一个相比是多余的了?其实也不是,因为wait的包容性矩阵和上边的矩阵是不平等的,wait的包容性矩阵以为是在
DDL等待的状态下,制止DML继续进入wait矩阵就不写出来了,大家可以去代码里看下)。

– SCHEMA is for schemas (aka databases).

比如:

– TABLE is for tables and views.

TX1                    TX2                    TX3

– FUNCTION is for stored functions.

SELECT T1

– PROCEDURE is for stored procedures.

DROP  T1

– TRIGGER is for triggers.

SELECT T1

– EVENT is for event scheduler events.

那时候候TX2会阻塞,TX3也会堵塞,被TX2阻塞,也正是说被wait的轩然大波阻塞了,那样可能正是为了保证在DDL等待时,禁止再做DML了,因为在DDL前边,DML显得确实不是那么重大了。

– COMMIT is for enabling the global read lock to block commits.

哪些唤醒被等候的职业呢?比如唤醒TX2,当TX1了事时,会调用release_all_locks_for_name,对被锁住的事务进行提醒,具体操作封装在reschedule_waiters函数中,重新设置等待时间的号子位举行提示,珍视代码如下:

– USER_LEVEL_LOCK is for user-level locks.

if (can_grant_lock(ticket->get_type(), ticket->get_ctx()))      {        if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED))        {          /*            Satisfy the found request by updating lock structures.            It is OK to do so even after waking up the waiter since any           session which tries to get any information about the state of           this lock has to acquire MDL_lock::m_rwlock first and thus,            when manages to do so, already sees an updated state of the            MDL_lock object.          */          m_waiting.remove_ticket(ticket);          m_granted.add_ticket(ticket);      } 

– LOCKING_SERVICE is for the name plugin RW-lock service

明天把mdl系统一整合体上看了一晃,对锁的呼吁、等待以及提醒有了开首掌握。并发性的难点是最难调节和测试的,我们若是想做锁方面包车型客车尝试,能够动用VS调节和测试中的冻结线程的功力,那样就足以保险出现情形决定完全依照你设计思路去表现。

3、完结分类

MDL,Meta Data
lock,元数据锁,一般称为字典锁。字典锁与数码锁相对应。字典锁是为了掩护数量对象被改造,一般是部分DDL会对字…

scope lock:一般对应全局MDL LOCK 如flush table with read lock 为namespace
space:GLOBAL type:S

object lock:如其名字,对象级其他MDL LOCK,比如TABLE

上面是源码中的注释:

 /**
  Helper struct which defines how different types of locks are handled
  for a specific MDL_lock. In practice we use only two strategies: "scoped"
  lock strategy for locks in GLOBAL, COMMIT, TABLESPACE and SCHEMA namespaces
  and "object" lock strategy for all other namespaces.
 */

4、MDL包容矩阵

scope lock:
     | Type of active  |
 Request |  scoped lock  |
  type  | IS(*) IX  S X |
 ---------+------------------+
 IS    | +   +  + + |
 IX    | +   +  - - |
 S    | +   -  + - |
 X    | +   -  - - |

object lock:
    Request | Granted requests for lock      |
    type  | S SH SR SW SWLP SU SRO SNW SNRW X |
   ----------+---------------------------------------------+
   S     | +  +  +  +  +  +  +  +  +  - |
   SH    | +  +  +  +  +  +  +  +  +  - |
   SR    | +  +  +  +  +  +  +  +  -  - |
   SW    | +  +  +  +  +  +  -  -  -  - |
   SWLP   | +  +  +  +  +  +  -  -  -  - |
   SU    | +  +  +  +  +  -  +  -  -  - |
   SRO    | +  +  +  -  -  +  +  +  -  - |
   SNW    | +  +  +  -  -  -  +  -  -  - |
   SNRW   | +  +  -  -  -  -  -  -  -  - |
   X     | -  -  -  -  -  -  -  -  -  - |

5、MDL
duration及MDL持续到几时

那个也非常少用过多解释,看源码注释就能够

MDL_STATEMENT:Locks with statement duration are automatically released at the end
       of statement or transaction.
MDL_TRANSACTION: Locks with transaction duration are automatically released at the end
        of transaction
MDL_EXPLICIT:Locks with explicit duration survive the end of statement and transaction.
       They have to be released explicitly by calling MDL_context::release_lock().

6、MDL LOCK FAST PATH(unobtrusive) OR
SLOW PATH(obtrusive)

选用三种不一样的主意目的在于优化MDL lock的兑现,上边是源码的讲明

A) "unobtrusive" lock types
      1) Each type from this set should be compatible with all other
        types from the set (including itself).
      2) These types should be common for DML operations
     Our goal is to optimize acquisition and release of locks of this
     type by avoiding complex checks and manipulations on m_waiting/
     m_granted bitmaps/lists. We replace them with a check of and
     increment/decrement of integer counters.
     We call the latter type of acquisition/release "fast path".
     Use of "fast path" reduces the size of critical section associated
     with MDL_lock::m_rwlock lock in the common case and thus increases
     scalability.
     The amount by which acquisition/release of specific type
     "unobtrusive" lock increases/decreases packed counter in
     MDL_lock::m_fast_path_state is returned by this function.
B) "obtrusive" lock types
      1) Granted or pending lock of those type is incompatible with
        some other types of locks or with itself.
      2) Not common for DML operations
     These locks have to be always acquired involving manipulations on
     m_waiting/m_granted bitmaps/lists, i.e. we have to use "slow path"
     for them. Moreover in the presence of active/pending locks from
     "obtrusive" set we have to acquire using "slow path" even locks of
     "unobtrusive" type.

7、MDL_request类

相当于通过言语深入分析后需求获得的MDL
LOCK的要求,然后经过那些类对象在MDL子系统
中打开MDL LOCK申请,大概包蕴如下一些特性

/** Type of metadata lock. */
 enum enum_mdl_type type; //需求的类型
 /** Duration for requested lock. */
 enum enum_mdl_duration duration; //持续时间
 /**
  Pointers for participating in the list of lock requests for this context.
 */
 MDL_request *next_in_list; //双向链表实现
 MDL_request **prev_in_list;
 /**
  Pointer to the lock ticket object for this lock request.
  Valid only if this lock request is satisfied.
 */
 MDL_ticket *ticket; //注意这里如果申请成功(没有等待),会指向一个实际的TICKET,否则为NULL
 /** A lock is requested based on a fully qualified name and type. */
 MDL_key key;//注意这里是一个MDL_KEY类型,主要的就是前面说的NAMESPACE+DB+OBJECT_NAME

MDL_key类,正是事实上的NAMESPACE+DB+OBJECT_NAME,整个放到一个char数组里面,他会是MDL_LOCK和MDL_REQUEST中出现

private:

uint16 m_length;

uint16 m_db_name_length;

char m_ptr[MAX_MDLKEY_LENGTH];//放到了那边

8、MDL_ticket

宛如门票同样,假使获得了MDL
LOCK必然给MDL_request再次回到一张登台券,假如等待则不会源码MDL_context::acquire_lock

可以观测到。当然那也是自己重要考察的一个类

/**
  Pointers for participating in the list of lock requests for this context.
  Context private.正如解释这里是context中链表链表的形成,是线程私有的
 */
 MDL_ticket *next_in_context;
 MDL_ticket **prev_in_context;
 /**
  Pointers for participating in the list of satisfied/pending requests
  for the lock. Externally accessible.正如解释这里是MDL_LOCK中链表链表的形成,是全局的
 */
 MDL_ticket *next_in_lock;
 MDL_ticket **prev_in_lock;
/**
  Context of the owner of the metadata lock ticket. Externally accessible.
  很明显这里指向了这个ticket的拥有者也就是MDL_context,它是线程的属性
 */
 MDL_context *m_ctx; 
 /**
  Pointer to the lock object for this lock ticket. Externally accessible.
  很明显这里是一个指向MDL_LOCK的一个指针
 */
 MDL_lock *m_lock;
 /**
  Indicates that ticket corresponds to lock acquired using "fast path"
  algorithm. Particularly this means that it was not included into
  MDL_lock::m_granted bitmap/list and instead is accounted for by
  MDL_lock::m_fast_path_locks_granted_counter
  这里就代表了是否是FAST PATH从注释来看fast path方式不会在MDL LOCK中
  占用granted位图和链表取而代之代之的是一个统计器m_fast_path_locks_granted_counter
  这样一来开销肯定更小
 */
 bool m_is_fast_path;
 /**
  Indicates that ticket corresponds to lock request which required
  storage engine notification during its acquisition and requires
  storage engine notification after its release.
 */
 bool m_hton_notified;