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 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数 ...
随机推荐
- Intel NUC迷你机2019年底迎来i9 8核心16线程
Intel处理器这两年全年提速,虽然10nm新工艺受阻,但核心数在全面增加,从发烧到桌面到低功耗莫不如此,如今连NUC迷你机也要全新进化了,一年多之后就会迎来8核心16线程,而且也划入i9序列. 根据 ...
- python 异步IO-aiohttp与简单的异步HTTP客户端/服务器
参考链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143209814 ...
- C# 从需要登录的网站上抓取数据
[转] C# 从需要登录的网站上抓取数据 背景:昨天一个学金融的同学让我帮她从一个网站上抓取数据,然后导出到excel,粗略看了下有1000+条记录,人工统计的话确实不可能.虽说不会,但作为一个学计算 ...
- [Python] Accessing Array Elements
NumPy Reference: Indexing Note: Indexing starts at 0 (zero). def slicing(): a = np.random.rand(5,4) ...
- linux 不常用命令及命令组合
lsof:list open files, sudo lsof | grep deleted:则列出虽然被删除,但还处于打开状态的文件.注意,这些文件占用的空间,只有在这些文件关闭时,才会被释放. m ...
- 23. Angular 中用 a 标签 href 路由时在浏览器中显示异常 "%2F" 路由失败问题1
这个是angular1.6默认给hash路由上添加了!(感叹号),导致出错,修改方法如下(添加配置,去掉默认前缀感叹号): angular.module('routingDemoApp',['ng ...
- POJ 3629 队列模拟
听说STL会卡T 然后我就试了一发 哈哈哈哈哈哈哈哈哈哈 1000ms卡时过的 这很值得我写一发题解了 哈哈哈哈哈哈哈哈哈哈哈哈 //By SiriusRen #include <queue&g ...
- NARF(Normal Aligned Radial Feature)关键点
NARF(Normal Aligned Radial Feature)关键点是为了从深度图像中识别物体而提出的,对NARF关键点的提取过程有以下要求: a) 提取的过程考虑边缘以及物体表面变化信息在内 ...
- Xcode Git 客户端 + GitBucket 服务器 使用整合归纳
1.使用前说明: 不知道XCode,Git的请自行度娘,不知道GitBucket的,可参考文章:git 私服搭建-gitbucket 初试牛刀 2.创建Git步骤 1>在gitbucket创建账 ...
- android+myeclipse+mysql下拉框数据绑定
原创作品,允许转载,转载时请务必声明作者信息和本声明.http://www.cnblogs.com/zhu520/p/8027036.html 本人小白,那个大神看到有问题可指出,谢谢.... 一:我 ...