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 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数 ...
随机推荐
- 【Codeforces Round #423 (Div. 2) C】String Reconstruction
[Link]:http://codeforces.com/contest/828/problem/C [Description] 让你猜一个字符串原来是什么; 你知道这个字符串的n个子串; 且知道第i ...
- 【Codeforces Round #422 (Div. 2) A】I'm bored with life
[题目链接]:http://codeforces.com/contest/822/problem/A [题意] 让你求a!和b!的gcd min(a,b)<=12 [题解] 哪个小就输出那个数的 ...
- HTML学习----------DAY1 第三节
本章通过实例向您演示最常用的 HTML 标签. 提示:不要担心本章中您还没有学过的例子,您将在下面的章节中学到它们. 提示:学习 HTML 最好的方式就是边学边做实验.我们为您准备了很好的 HTML ...
- [B cannot be cast to java.lang.String
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.inv ...
- unix mkdir命令的使用方法
[语法]: mkdir [-m 模式] [-p] 文件夹名 [说明]: 本命令用于建立文件夹,文件夹的存取模式由掩码(umask)决定,要求对其父文件夹具有写权限,文件夹的UID和GID为实际 ...
- cocos2d-x 3.0正式版 vs2013配置
cocos2d-x 3.0正式版与之前的版本号差异较大,曾经的教程非常多都不使用了. 1.从cocos2d-x官网http://www.cocos2d-x.org下载3.0版的压缩包,随便解压一个位置 ...
- BZOJ 2982 combination Lucas定理
题目大意:发上来就过不了审核了--总之大意就是求C(n,m) mod 10007 m,n∈[1,2*10^8] 卢卡斯定理:C(n,m)=C(n%p,m%p)*C(n/p,m/p) mod p 要求p ...
- Python(十一) 原生爬虫
一.分析抓取目的确定抓取页面 #爬取主播人气排行 二.整理爬虫常规思路 爬虫前奏 明确目的 找到数据对应的网页 分析网页的结构找到数据所在的标签位置 模拟 HTTP 请求, 向服务器发送这个请 ...
- Python(五) 包、模块、函数与变量作用域
一.while循环与使用场景 CONDITION=1 while CONDITION <=5 : CONDITION +=1 print("hello") else: pri ...
- Java main方法中的String[] args
-- Java 命令行参数 -- 关于其中的args以及public static / static public Java 命令行参数 前面已经看到多个使用Java数组的示例,每一个Java应用程序 ...