MySQL 深潜 - MDL 锁的实现与获取机制

MySQL的Metadata Locking (MDL)机制用于事务隔离和一致性,涉及不同类型的MDL锁及兼容性。本文深入探讨MDL的实现,包括基本概念如MDL_key和enum_mdl_type,数据结构如MDL_lock和MDL_ticket,以及获取过程,特别是锁等待、死锁检测。此外,介绍了PolarDB在MDL上的优化,实现了分区级别的MDL锁以提高并发度。
摘要由CSDN通过智能技术生成

一 背景

为了满足数据库在并发请求下的事务隔离性和一致性要求,同时针对 MySQL 插件式多种存储引擎都能发挥作用,MySQL 在 Server 层实现了 Metadata Locking(MDL)机制。达到的效果比如可以在事务访问数据库的某种资源时,限制其他并发事务删除该资源。这是一种逻辑意义上的锁,与操作系统内核提供的有限种类 mutex 不同,MDL 可以灵活自定义锁的对象、锁的类型以及不同锁类型的优先级,甚至可以做到在系统不同状态时动态调整不同锁类型的兼容性,极大的方便了数据库对各种查询请求进行合理的并发控制。

本文将介绍在 MDL 系统中常用的数据结构及含义,然后从实现角度讨论 MDL 的获取机制与死锁检测,最后分享在实践中如何监控 MDL 状态。

二 基本概念

1 MDL_key

MDL 的对象是采用键值对(key-value)的方式描述的,每一个 key 值都唯一的代表了锁的对象(value 代表数据库的某种资源)。key 是由 MDL_key 表示的,用字符串的形式表示了对象的名称。

完整的字符串由 namespace、按层次每一级的名称组成,多种命名空间可以将不同类型的同名对象区分开。命名空间包括 GLOBAL、SCHEMA、TABLE、FUNCTION、PROCEDURE 等数据库中可以创建的不同对象类型组成。

对象的名称根据类型的不同可以由多种层次组成。比如表对象就由数据库名和表名唯一的描述;如果是 SCHEMA 对象,那就只有数据库名这一个层次。名称之间用字符串结束符 '\0' 分隔。因此由这几部分组成的字符串整体就能作为 key 唯一的表示数据库的某种对象。

2 enum_mdl_type

对于同一个数据库对象而言,不同的查询也有着不同的访问模式,比如 SELECT 语句是想要读取对象的内容,INSERT / UPDATE 语句是想要修改对象的内容,DDL 语句是想要修改对象的结构和定义。这些语句对于对象的影响程度和并发隔离性的要求不同,因此 MySQL 定义了不同类型的 MDL 以及他们之间的兼容性来控制这些语句的并发访问。

MDL 的类型由 enum_mdl_type 表示,最常用的类型包括:

  • MDL_SHARED(S),可以共享访问对象的元数据,比如 SHOW CREATE TABLE 语句
  • MDL_SHARED_READ(SR),可以共享访问对象的数据,比如 SELECT 语句
  • MDL_SHARED_WRITE(SW),可以修改对象的数据,比如 INSERT / UPDATE 语句
  • MDL_SHARED_UPGRADABLE(SU),可升级的共享锁,后面可升级到更强的锁(比如 X 锁,阻塞并发访问),比如 DDL 的第一阶段
  • MDL_EXCLUSIVE(X),独占锁,阻塞其他线程对该对象的并发访问,可以修改对象的元数据,比如 DDL 的第二阶段

不同的查询语句通过请求不同类型的 MDL,结合不同类型的 MDL 之间灵活定制的兼容性,就可以对相互冲突的语句进行并发控制。对于同一对象而言,不同类型的 MDL 之间的默认兼容性如下所述。

不同类型的 MDL 兼容性

MySQL 将锁类型划分为范围锁和对象锁。

1)范围锁

范围锁种类较少(IX、S、X),主要用于 GLOBAL、COMMIT、TABLESPACE、BACKUP_LOCK 和 SCHEMA 命名空间的对象。这几种类型的兼容性简单,主要是从整体上去限制并发操作,比如全局的读锁来阻塞事务提交、DDL 更新表对象的元信息通过请求 SCHEMA 范围的意向独占锁(IX)来阻塞 SCHEMA 层面的修改操作。

这几种类型的 MDL 兼容性关系由两个矩阵定义。对于同一个对象来说,一个是已经获取到的 MDL 类型对新请求类型的兼容性情况;另一个是未获取到,正在等待的 MDL 请求类型对新请求类型的兼容性。由于 IS(INTENTION_SHARE) 在所有情况下与其他锁都兼容,在 MDL 系统中可忽略。

| Type of active   |
Request |   scoped lock    |
 type   | IS(*)  IX   S  X |
---------+------------------+
IS       |  +      +   +  + |
IX       |  +      +   -  - |
S        |  +      -   +  - |
X        |  +      -   -  - |
        
         |    Pending      |
 Request |  scoped lock    |
  type   | IS(*)  IX  S  X |
 ---------+-----------------+
IS       |  +      +  +  + |
IX       |  +      +  -  - |
S        |  +      +  +  - |
X        |  +      +  +  + |

Here: "+" -- means that request can be satisfied
"-" -- means that request can't be satisfied and should wait

2)对象锁

对象锁包含的 MDL 类型比较丰富,应用于数据库绝大多数的基本对象。它们的兼容性矩阵如下:

Request  |  Granted requests for lock            |
   type    | S  SH  SR  SW  SWLP  SU  SRO  SNW  SNRW  X  |
 ----------+---------------------------------------------+
 S         | +   +   +   +    +    +   +    +    +    -  |
 SH        | +   +   +   +    +    +   +    +    +    -  |
 SR        | +   +   +   +    +    +   +    +    -    -  |
 SW        | +   +   +   +    +    +   -    -    -    -  |
 SWLP      | +   +   +   +    +    +   -    -    -    -  |
 SU        | +   +   +   +    +    -   +    -    -    -  |
 SRO       | +   +   +   -    -    +   +    +    -    -  |
 SNW       | +   +   +   -    -    -   +    -    -    -  |
 SNRW      | +   +   -   -    -    -   -    -    -    -  |
 X         | -   -   -   -    -    -   -    -    -    -  |
        
  Request  |         Pending requests for lock          |
   type    | S  SH  SR  SW  SWLP  SU  SRO  SNW  SNRW  X |
 ----------+--------------------------------------------+
 S         | +   +   +   +    +    +   +    +     +   - |
 SH        | +   +   +   +    +    +   +    +     +   + |
 SR        | +   +   +   +    +    +   +    +     -   - |
 SW        | +   +   +   +    +    +   +    -     -   - |
 SWLP      | +   +   +   +    +    +   -    -     -   - |
 SU        | +   +   +   +    +    +   +    +     +   - |
 SRO       | +   +   +   -    +    +   +    +     -   - |
 SNW       | +   +   +   +    +    +   +    +     +   - |
 SNRW      | +   +   +   +    +    +   +    +     +   - |
 X         | +   +   +   +    +    +   +    +     +   + |
        
  Here: "+" -- means that request can be satisfied
        "-" -- means that request can't be satisfied and should wait

在 MDL 获取过程中,通过这两个兼容性矩阵,就可以判断当前是否存在与请求的 MDL 不兼容的 granted / pending 状态的 MDL,来决定该请求是否能被满足,如果不能被满足则进入 pending 等待状态。

MDL 系统也通过兼容性矩阵来判断锁类型的强弱,方法如下:

/**
  Check if ticket represents metadata lock of "stronger" or equal type
  than specified one. I.e. if metadata lock represented by ticket won't
  allow any of locks which are not allowed by specified type of lock.

  @return true  if ticket has stronger or equal type
          false otherwise.
*/
bool MDL_ticket::has_stronger_or_equal_type(enum_mdl_type type) const {
  const MDL_lock::bitmap_t *granted_incompat_map =
      m_lock->incompatible_granted_types_bitmap();

  return !(granted_incompat_map[type] & ~(granted_incompat_map[m_type]));
}

表达式的写法有点绕,可以理解为,如果 type 类型与某种 m_type 类型兼容的 MDL 不兼容,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值