1 元数据锁的锁请求与锁等待

    元数据锁在MySQL Server层,依照锁的状态被细分为两种。一种是已经施加的锁。一种是等待施加的锁即锁请求,这样被区分的原因,如MySQL对“class MDL_request”的代码凝视作了解释:

/**

  A pending
metadata lock request.

 

  A lock
request and a granted metadata lock are represented by

  different
classes because they have different
allocation

  sites and hence different lifetimes. The allocation of lock requests is     //注意这里给出的原因是从project实践中对锁的实现的角度区分的

  controlled
from outside of the MDL subsystem,
while allocation of granted   //体现了project与理论的不同

  locks
(tickets) is controlled within the MDL
subsystem
.

 

  MDL_request
is a C structure, you don't need to call a constructor

  or
destructor for it.

*/

class MDL_request{...}  //锁请求

    所以,元数据锁在使用的过程中又被细分为“lock granted
metadata” (代码中使用“class MDL_ticket”表示。

ticket,入场卷。即要被授予的锁)和“lock request metadata”(代码中使用“class MDL_request”表示加锁的请求)。

这样,MySQL Server分别使用两个类来表示这两种被细分的锁。

    当锁请求要求施加锁不成功的时候,则产生锁等待,而锁等待则用MDL_wait表示。

/**A reliable way to wait on an MDL lock. */

class MDL_wait{...  //锁等待。在获取锁的过程中,须要为是否获得锁做标志。採用的就是锁等待的状态值

enum enum_wait_status
{ //锁等待的状态,在锁等待在生命周期内因不同操作产生不同结果

    EMPTY = 0, //空状态。初始值

    GRANTED,   //锁被授予的状态

    VICTIM,    //某个会话被选为了受害者

    TIMEOUT,  
//超时状态,申请加锁却发生超时

    KILLED }; 
//被killed状态,发起锁请求的会话被killed掉。所以不仅是发起加锁请求的事务应终止,事务的属主会话也被终止

...}

2 元数据锁类对象

    保存每一MDL_key相应的全部已经授予的MDL锁信息,由于MDL_key标识了不同的数据库对象类,不同的数据库对象类上所施加的锁之间的兼容性因对象存在区别,所以定义了不同的策略来区分这些区别。请注意,MDL_lock不是一个详细的锁,而是一类锁的集合

GLOBAL和COMMIT类的锁。是全局唯一的。除此之外的其它类型的锁,能够有多个。

/**

The lock context. Created internally for an
acquired lock.

 For a given
name, there exists only one MDL_lock instance,and it
exists only when the lock has been granted

Can be seen
as an MDL subsystem's version of TABLE_SHARE
.  //能够被存储层的TABLE_SHARE使用这个锁对象

 

This is an abstract class which lacks information
aboutcompatibility rules for lock types.

 They should
be specifiedin its descendants. 

*/

class MDL_lock  //当须要施加元数据锁的时候。生成一个MDL_lock锁对象

{...

    class Ticket_list{...}  //把MDL_ticket封装为一个 List对象,用以存放多个MDL_ticket锁对象(MDL_ticket參见下一小节)

 

    /**  //对于锁的操作,又存在两种策略。这是依据被加锁的对象的特定区分的。

每一种策略分别有各自的锁兼容规则

      Helper struct which defines how different
types of locks are handledfor 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.                                 //对象锁策略:数据库内部的各种对象

     */

    struct MDL_lock_strategy
//锁的施加策略。如上所述,锁被分为两种类型,所以统一用策略数据结构来管理和描写叙述这两类锁的特性

    {

        /**Compatibility (or rather
"incompatibility") matrices for lock types. //新申请的锁向已经授予的锁进行锁的相容性推断

            Array of bitmaps which elements specify which granted locks areincompatible with
the type of lock being requested.*/   

        bitmap_tm_granted_incompatible[MDL_TYPE_END];  //已经被授予的锁的数组中保存有不兼容的、准备申请此对象的请求锁,位图数组结构

 

        //新申请的锁向已经正在等待的锁进行锁的相容性(优先级)推断。此数组的作用有两个:

        //一是通过m_waiting_incompatible[0]。

        //二是防止产生锁饥饿现象,

        //所以添加了对低优先级锁的申请次数的计数。当计数到一定程度时,唤醒低优先级的尚没获得锁的会话。

        //能够关注MDL_lock::reschedule_waiters()函数。查看对等待的锁的处理方式;看其调用者查看唤醒条件。

        //另外看此函数中封锁粒度较强的锁释放而封锁粒度较弱的锁得以有机会被授予的时候,

        //m_hog_lock_count/m_piglet_lock_count有机会被重置

        //(注意强弱是相对的,取决于11.4.1节中第3小节中定义的enum_mdl_type中的锁的粒度值。据这些值比較大小)

         /** Arrays
of bitmaps which elements specify which waiting
locks
areincompatible with the type of lock being requested.

            Basically, eacharray defines priorities
between lock types.

           We need
4 separate arrays since in order to prevent starvation for some of lock request
types, we use different priority matrices:

          0) in "normal" situation.  //正常优先级

          1) in situation when the number of
successively granted "piglet" requestsexceeds the
max_write_lock_count limit. //小猪优先级

          2) in situation when the number of
successively granted "hog" requestsexceeds the max_write_lock_count
limit. //猪优先级

          3) in situation when both "piglet"
and "hog" counters exceed limit.*/ 
//小猪和猪之和

        //这个矩阵是某个锁请求与处于等待状态的锁的优先级比較表

         //第一个数组是正常情况,其它三个数组是为解决锁饥饿而设置的

         //如m_piglet_lock_count的值大于了max_write_lock_count。则m_waiting_incompatible[1][x]被置位

        //如m_hog_lock_count的值大于了max_write_lock_count。则m_waiting_incompatible[2][x]被置位

        //在等待的锁的数组中保存有不兼容的、准备申请此对象的请求锁,二维位图数组结构

        bitmap_tm_waiting_incompatible[4][MDL_TYPE_END];//piglet,会申请SW锁;hog。会申请X、SNRW、SNW这三者其一

 

        /**Array of increments for
"unobtrusive" types of lock requests for locks
.

           @sa
MDL_lock::get_unobtrusive_lock_increment().*/

        //“unobtrusive”类型相关的锁粒度包含: S、SH、SR 和SW。相应“Fast path”的訪问方式,主要用于DML类操作

        //“obtrusive” 类型相关的锁粒度包含:SU、SRO、SNW、SNRW、X。相应“slow path”的訪问方式,主要用于非DML类操作

        fast_path_state_tm_unobtrusive_lock_increment[MDL_TYPE_END];
//高速訪问“unobtrusive”类型的锁

 

        /**Indicates that locks of this type are
affected bythe max_write_lock_count limit.*/

        bool m_is_affected_by_max_write_lock_count;

 

        /**Pointer to a static method which determines
if the type of lockrequested requires
notification of conflicting locks
.

           NULL if
thereare no lock types requiring notification.*/

        //当有冲突锁的时候,是否要被通知。

“scopedlock”不要求被通知。而“object lock”施加排它锁时才须要被通知

        bool (*m_needs_notification)(const MDL_ticket
*ticket);

 

        /**Pointer to a static method which allows
notification of owners ofconflicting locksabout the fact

           that a
type of lock requiringnotification was requested.*/

        //对于“object lock”,通知持有S、SH类锁的会话线程(可能与待定的X锁冲突。pending lock)

        void (*m_notify_conflicting_locks)(MDL_context
*ctx, MDL_lock *lock); //发出通知的函数,含义相似上面

 

        /**Pointer to a static method which converts
information aboutlocks granted using "fast" path

           from
fast_path_state_trepresentation to bitmap of lock types.*/

        //S、SR、SW粒度的锁能够被使用“fast path”方式高速处理

        bitmap_t (*m_fast_path_granted_bitmap)(const MDL_lock &lock);

 

         /**Pointer
to a static method which determines if waiting for the lockshould be aborted

           when
connection is lost. NULL if locks ofthis type don't require such aborts.*/ //当连接断开的时候,锁是否应该被撤销。

        //LOCKING_SERVICE和USER_LEVEL_LOCK加锁的情况可被撤销,如通过GET_LOCK()施加的锁

        bool (*m_needs_connection_check)(const
MDL_lock *lock);

    };

 

public:

    /** The key of the object (data) being
protected. */

     MDL_key key;   //元数据锁所属的类型(在MDL_key中把元数据这种对象分为了几类,给每类定义一个key在enum_mdl_namespace枚举中)

    /** List
of granted tickets for this lock. */

   
Ticket_list m_granted;  //对于本锁而言,在系统内部存在的已经被授予的全部锁list

    /**
Tickets for contexts waiting to acquire a lock. */

Ticket_list
m_waiting; //对于本锁而言,在系统内部存在的正在等待被授予的全部锁list

//如上两个list,配合使用:

//当要获取一个锁(入通过acquire_lock()函数)不成功时。把新生成的一个MDL_ticket对象放入等待队列。获取成功。则放入m_granted中

//当一个处于等待状态的锁能够被授予的时候(can_grant_lock()推断能否够被授予)。就从m_waiting中remove掉,然后添加到m_granted中,

//这种事情,当获取锁或释放锁时,或因ALTER
TABLE等操作须要降级锁时,通过reschedule_waiters()函数进行

...

    /** Pointer to strategy object which defines
how different types of lock

        requests should be handled for the namespace
to which this lock belongs.

        @sa MDL_lock::m_scoped_lock_strategy and
MDL_lock:m_object_lock_strategy. */

    const MDL_lock_strategy *m_strategy;
//注意这是一个指针。运行哪个类型的策略就表示使用被指向的策略对象之策略(指向以下两个策略对象之中的一个)

...

    static const MDL_lock_strategy m_scoped_lock_strategy; //范围锁相应的策略

    static const MDL_lock_strategy m_object_lock_strategy; //对象锁相应的策略

};

MDL--元数据锁的锁请求与锁等待+元数据锁类对象的更多相关文章

  1. 浅谈SQL Transaction在请求中断后的行锁表锁

    最近在维护Web Service接口时,由于数据数据量达到千万级别,接口调用不时出现错误让人不胜烦恼,经过性能测试查出瓶颈在数据库数据处理上,可着实忙了一番.相信众多程序猿和DBA都会头痛性能的问题, ...

  2. 锁(MySQL篇)—之MyISAM表锁

    前言 锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是 ...

  3. MySQL锁和事务(一):InnoDB锁(MySQL 官方文档粗翻)

    // 写在前面,实际上,数据库加锁的类型和范围受到多种因素的影响,例如数据库隔离等级,SQL语句,是否使用主键.索引等等.可以查看博文: http://www.cnblogs.com/zhaoyl/p ...

  4. redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  5. InnoDB的锁机制浅析(二)—探索InnoDB中的锁(Record锁/Gap锁/Next-key锁/插入意向锁)

    Record锁/Gap锁/Next-key锁/插入意向锁 文章总共分为五个部分: InnoDB的锁机制浅析(一)-基本概念/兼容矩阵 InnoDB的锁机制浅析(二)-探索InnoDB中的锁(Recor ...

  6. redis实现分布式锁需要考虑的因素以及可重入锁实现

    死锁 错误例子 解决方式  防止死锁 通过设置超时时间  不要使用setnx key   expire 20  不能保证原子性 如果setnx程序就挂了 没有执行expire就死锁了  reidis2 ...

  7. 详解Java锁的升级与对比(1)——锁的分类与细节(结合部分源码)

    前言 之前只是对Java各种锁都有所认识,但没有一个统一的整理及总结,且没有对"锁升级"这一概念的加深理解,今天趁着周末好好整理下之前记过的笔记,并归纳为此博文,主要参考资源为&l ...

  8. Redisson 分布式锁源码 01:可重入锁加锁

    前言 相信小伙伴都是使用分布式服务,那一定绕不开分布式服务中数据并发更新问题! 单系统很容易想到 Java 的各种锁,像 synchronize.ReentrantLock 等等等,那分布式系统如何处 ...

  9. 【数据库】数据库的锁机制,MySQL中的行级锁,表级锁,页级锁

    转载:http://www.hollischuang.com/archives/914 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数 ...

随机推荐

  1. Python组织文件 实践:拷贝某种类型的所有文件

    #! python3 #chapter09-test01- 遍历目录树,查找特定扩展名的文件不论这些文件的位置在哪里,都将他们 #拷贝到一个新的文件夹中 import os,shutil,pprint ...

  2. 紫书 习题 10-1UVa 111040(找规律)

    通过观察可以得 图可以分成很多个上面一个,中间两个,下面三个的"模板" 这个时候最上面一个知道,最下面得左右知道 那么可以设下面中间为x,左边为a1, 右边为a2, a1a2已知 ...

  3. [WC2011]最大XOR和路径(线性基)

    P4151 [WC2011]最大XOR和路径 题目描述 XOR(异或)是一种二元逻辑运算,其运算结果当且仅当两个输入的布尔值不相等时才为真,否则为假. XOR 运算的真值表如下( 1 表示真, 0 表 ...

  4. 华为:一张图看懂 HBase

    来自为知笔记(Wiz)

  5. 二 JDK + mysql + yum + rpm

    如果系统环境崩溃.   调用/usr/bin/vim /etc/profile   1  网络搭建 2  host配置 3  SSH无密码登录   4  rpm 安装     yum install ...

  6. caioj1442:第k小的数Ⅱ

    [传送门:caioj1442] 简要题意: 给出n个点,每个点都有一个权值,m个操作,操作有两种:第一种是询问l到r的第k小的值,然后输出这个值,第二种是将第x个点的值改为k 题解: 又是一道主席树的 ...

  7. POJ 3189 二分+Dinic

    题意: 思路: 二分跨度 枚举最低座次 建图:源点向每头牛连边权为1的边 每头牛向当前枚举的B的区间这段连上边权为1的边 所有座次向汇点连边权为牛棚容量的边 判判流量是不是等于n 一开始写得是直接枚举 ...

  8. WebAssembly学习(一):认识WebAssembly

    WebAssembly作为一门新兴起的技术,在 JavaScript 圈非常的火!人们都在谈论它多么多么快,怎样怎样改变 Web 开发领域,被各大巨头所推广,这篇文章对其做一个简单的了解认识,本文非原 ...

  9. 原生js实现多组图片切换

    这几天一直在练习原生js写效果,需要理清自己的逻辑,做了一个切换多组图片的效果: css样式: * { margin: 0; padding: 0; } body { background: #303 ...

  10. python全栈_day01

    计算机容量 1位 = 1bit  8bit = 1byte = 1字节      1024bytes = 1kbytes =1KB  1024个字符,小文档 ,几百k可以表示一张图片  1024KB ...