MDL--元数据锁的锁请求与锁等待+元数据锁类对象
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--元数据锁的锁请求与锁等待+元数据锁类对象的更多相关文章
- 浅谈SQL Transaction在请求中断后的行锁表锁
最近在维护Web Service接口时,由于数据数据量达到千万级别,接口调用不时出现错误让人不胜烦恼,经过性能测试查出瓶颈在数据库数据处理上,可着实忙了一番.相信众多程序猿和DBA都会头痛性能的问题, ...
- 锁(MySQL篇)—之MyISAM表锁
前言 锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是 ...
- MySQL锁和事务(一):InnoDB锁(MySQL 官方文档粗翻)
// 写在前面,实际上,数据库加锁的类型和范围受到多种因素的影响,例如数据库隔离等级,SQL语句,是否使用主键.索引等等.可以查看博文: http://www.cnblogs.com/zhaoyl/p ...
- redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- InnoDB的锁机制浅析(二)—探索InnoDB中的锁(Record锁/Gap锁/Next-key锁/插入意向锁)
Record锁/Gap锁/Next-key锁/插入意向锁 文章总共分为五个部分: InnoDB的锁机制浅析(一)-基本概念/兼容矩阵 InnoDB的锁机制浅析(二)-探索InnoDB中的锁(Recor ...
- redis实现分布式锁需要考虑的因素以及可重入锁实现
死锁 错误例子 解决方式 防止死锁 通过设置超时时间 不要使用setnx key expire 20 不能保证原子性 如果setnx程序就挂了 没有执行expire就死锁了 reidis2 ...
- 详解Java锁的升级与对比(1)——锁的分类与细节(结合部分源码)
前言 之前只是对Java各种锁都有所认识,但没有一个统一的整理及总结,且没有对"锁升级"这一概念的加深理解,今天趁着周末好好整理下之前记过的笔记,并归纳为此博文,主要参考资源为&l ...
- Redisson 分布式锁源码 01:可重入锁加锁
前言 相信小伙伴都是使用分布式服务,那一定绕不开分布式服务中数据并发更新问题! 单系统很容易想到 Java 的各种锁,像 synchronize.ReentrantLock 等等等,那分布式系统如何处 ...
- 【数据库】数据库的锁机制,MySQL中的行级锁,表级锁,页级锁
转载:http://www.hollischuang.com/archives/914 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数 ...
随机推荐
- Vue和vue-template-compiler版本之间的问题
今天把远程仓库拉下项目,运行'npm run dev'时,报错 Module build failed: Error: Cannot find module 'vue-template-compile ...
- C语言函数--E
函数名: ecvt 功 能: 把一个浮点数转换为字符串 用 法: char ecvt(double value, int ndigit, int *decpt, int *sign); 程序例: #i ...
- 多client并发登录
//LoginClient.java package mySocket; import java.io.BufferedReader; import java.io.InputStreamReader ...
- jquery ajax中支持哪些返回类型以及js中判断一个类型常用的方法?
1 jquery ajax中支持哪些返回类型在JQuery中,AJAX有三种实现方式:$.ajax() , $.post , $.get(). 预期服务器返回的数据类型.如果不指定,jQuery 将自 ...
- BZOJ 1598 第k短路
思路: 先反向建图 Dijkstra一遍 求出h数组 再正向建图 A_star一遍 搞定 //By SiriusRen #include <queue> #include <cstd ...
- 一张图了解javaJwt
1.什么是javaJwt? JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims ...
- 路径+DataRow+SqlPara防止sql注入
绝对路径:是从盘符开始的路径,形如C:\windows\system32\cmd.exe相对路径:是从当前路径开始的路径,假如当前路径为C:\windows要描述上述路径,只需输入system32\c ...
- vmware-images
https://virtualboxes.org/images/centos/ https://www.osboxes.org/vmware-images/
- Callback<> and Bind()
Callback<> and Bind() Introduction The templated base::Callback<> class is a generalized ...
- 如何在Ubuntu14.04中安装mysql
接触过MySQL的小伙伴们都知道,在Windows下安装MySQL是一件让人十分头大的事情,但是在Ubuntu等其他Linux系统中安装MySQL就简单很多了,具体的教程如下.1.在Ubuntu的命令 ...