Chinaunix首页 | 论坛 | 博客
  • 博客访问: 867824
  • 博文数量: 179
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1546
  • 用 户 组: 普通用户
  • 注册时间: 2015-01-27 11:05
个人简介

MySQL工程师 QQ:1815357042

文章分类

全部博文(179)

文章存档

2015年(179)

分类: Mysql/postgreSQL

2015-03-06 12:15:45

转载自:

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



什么是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根据锁的类型我们也可以知道其兼容矩阵如下:

  IXSSHSRSWSNWSNRWX
  IX11111111
  S11111110
  SH11111110
  SR11111100
  SW11111000
  SNW11110000
  SNRW11100000
  X10000000


  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_request contains the needed ticket ) return ticket; End if; Create a ticket; If (!find lock in lock_sys) Create a lock; End if If (lock can be granted to mdl_request) Set lock to ticket; Set ticket to mdl_request; Else Wait for lock End if


  稍微解释下,首先是在mdl_request本身去查看有没有相等的或者stronger的ticket,如果存在,则直接使用。否则创建一个 ticket,查找上锁对象对应的lock,没有则创建
阅读(1307) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~