什么是MDL

MDL,Meta Data lock,元数据锁,一般称为字典锁。字典锁与数据锁相对应。字典锁是为了保护数据对象被改变,一般是一些DDL会对字典对象改变,如两个TX,TX1先查询表,然后TX2试图DROP,字典锁就会lock住TX2,知道TX1结束(提交或回滚)。数据锁是保护表中的数据,如两个TX同时更新一行时,先得到row lock的TX会先执行,后者只能等待。

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

支持的锁类型

数据库理论中的基本锁类型是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_WRITE锁之后,否则无法并发。这种应用场景应该是对一个较大的表进行ALTER时,其他事物仍然可以读,并发性得到了提高。

锁的兼容性

锁的兼容性就是我们经常看到的那些兼容性矩阵,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锁不互斥。

数据结构

涉及到的和锁相关的数据结构主要是如下几个:

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_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_requestcontainsthe needed ticket )

returnticket;

Endif;

Createa ticket;

If (!find lockinlock_sys)

Createa lock;

Endif

If (lock can be grantedtomdl_request)

Setlocktoticket;

Settickettomdl_request;

Else

Waitforlock

Endif

稍微解释下,首先是在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))

returncan_grant;

Endif

Endif

即首先判断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 requestbyupdating lock structures.

ItisOKtodo so evenafterwaking up the waiter sinceany

session which triestogetanyinformation about the stateof

this lock hastoacquire MDL_lock::m_rwlockfirstandthus,

whenmanagestodo so, already sees an updated stateofthe

MDL_lock object.

*/

m_waiting.remove_ticket(ticket);

m_granted.add_ticket(ticket);

}

今天把mdl系统总体上看了一下,对锁的请求、等待以及唤醒有了初步了解。并发性的问题是最难调试的,大家如果想做锁方面的实验,可以利用VS调试中的冻结线程的功能,这样就可以确保并发情况控制完全按照你设计思路去呈现。

【编辑推荐】

mysql mdl 锁_MySQL源码学习:MDL字典锁相关推荐

  1. MySQL mdl导入_MySQL源码学习——MDL字典锁

    什么是MDL MDL,Meta Data lock,元数据锁,一般称为字典锁.字典锁与数据锁相对应.字典锁是为了保护数据对象被改变,一般是一些DDL会对字典对象改变,如两个TX,TX1先查询表,然后T ...

  2. mysql源码学习 vc项目解决方案文件_Mysql源码学习——源码目录结构

    目录清单 目录名 注释 Bdb 伯克利DB表引擎 BUILD 构建工程的脚本 Client 客户端 Cmd-line-utils 命令行工具 Config 构建工程所需的一些文件 Dbug Fred ...

  3. mysql源码目录在哪_Mysql源码学习——源码目录结构

    目录清单 目录名 注释 Bdb 伯克利DB表引擎 BUILD 构建工程的脚本 Client 客户端 Cmd-line-utils 命令行工具 Config 构建工程所需的一些文件 Dbug Fred ...

  4. DevStore一键锁屏源码学习

    项目结构: 代码 MainActivity.java package com.test.lockscreen;import com.test.lockscreen.LockReceiver;impor ...

  5. Redis分布式锁解析源码分析

    Redis分布式锁解析&源码分析 概述 实战 简单的分布式锁 Redisson实现分布式锁 Redission源码分析 构造方法 获取锁lock 解锁 锁失效 红锁 案例分析 原始的写法 进化 ...

  6. 顾客信息表mysql_Qt5.5.0使用mysql编撰小软件源码讲解-顾客信息登记表_mysql

    Qt5.5.0使用mysql编写小软件源码讲解---顾客信息登记表 Qt5.5.0使用mysql编写小软件源码讲解---顾客信息登记表 一个个人觉得比较简单小巧的软件. 下面就如何编写如何发布打包来介 ...

  7. mysql5.5.8编译安装_Mysql应用linux下mysql 5.5.8 源码编译安装

    <MysqL应用linux下MysqL 5.5.8 源码编译安装>要点: 本文介绍了MysqL应用linux下MysqL 5.5.8 源码编译安装,希望对您有用.如果有疑问,可以联系我们. ...

  8. Gh0st源码学习(二)去除硬盘锁和驱动

    一.去除硬盘锁   GH0st硬盘锁是源码的作者为了保护版权而设置的,如果我们直接更改版权会造成硬盘被锁   中了硬盘锁的后果是非常严重的,特别是你电脑里有重要数据的时候,这样会导致你电脑里的数据全部 ...

  9. MySQL学习之路 一 : MySQL 5.7.19 源码安装

    MySQL 5.7.19 源码安装 查看系统: # cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) 安装依赖包 # yum - ...

最新文章

  1. 用python做一个图片验证码
  2. python 文字语音朗读-怎么用 Python 来朗读网页 ?
  3. Mendix发布全球低代码报告,中国软件与低代码发展远超全球
  4. httpurlconnect设置中文参数_CNC机床参数的设置及报警解除,赶紧收藏吧!
  5. Java笔记-CXF使用Adapter处理复杂类型(如Map)
  6. Pytorch —— 权值初始化
  7. java初_JAVA的初体验
  8. 大话西游之程序员做项目
  9. 2017下半年,一二线互联网公司Android面试题汇总
  10. iOS - OC NSFileManager 文件管理
  11. geo差异表达分析_GEO2R差异表达分析软件
  12. 双缓冲技术解决java游戏图片闪现问题
  13. Amoeba配置读写分离
  14. CANoe如何查看总线负载率?
  15. rimraf : 无法加载文件,‘set-executionpolicy‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  16. Intel Compute Sticks 电脑棒安装Ubuntu
  17. java毕业设计网上书城系统(附源码、数据库)
  18. Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-reso
  19. php添加表格行列,excel表格怎么插行和列?
  20. EZ CD Audio Converter

热门文章

  1. 齐鲁工业大学计算机科学与技术专业分数线,齐鲁工业大学计算机科学与技术专业2017年在山西理科高考录取最低分数线...
  2. VS中使用QT,多国语言翻译问题
  3. [模拟][模电][面试][运放]仪表放大器
  4. Zabbix5.0编译升级至6.0操作手册
  5. 搭建DNF台服之开启拍卖行
  6. 【转帖】一些常用网站列表
  7. 各类乱码类型及其产生原因
  8. 简单使用html+css+js随机获取一注双色球号码
  9. 计算机房的标准和规定,计算机房设计规范
  10. 亚马逊Kindle入华遇阻销量不佳 遭国内品牌围剿