Table of Contents
什么是MDL
MDL的设计目标
支持的锁类型
锁的兼容性
数据结构
Home Database Mysql Tutorial MySQL源码学习――MDL字典锁_MySQL

MySQL源码学习――MDL字典锁_MySQL

Jun 01, 2016 pm 01:44 PM
yes Lock

bitsCN.com

 

  • 什么是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_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,没有则创建。检查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))

    return can_grant;

    End if

End if

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

          It is OK to do so even after waking up the waiter since any

          session which tries to get any information about the state of

          this lock has to acquire MDL_lock::m_rwlock first and thus,

          when manages to do so, already sees an updated state of the

          MDL_lock object.

        */

        m_waiting.remove_ticket(ticket);

        m_granted.add_ticket(ticket);

    }

 

 

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

踏着落叶,追寻着我的梦想。转载请注明出处   作者 心中无码 bitsCN.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Roblox: Bubble Gum Simulator Infinity - How To Get And Use Royal Keys
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusion System, Explained
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers Of The Witch Tree - How To Unlock The Grappling Hook
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1665
14
PHP Tutorial
1270
29
C# Tutorial
1249
24
Python GIL (Global Interpreter Lock): Uncovering the principles and performance impact behind it Python GIL (Global Interpreter Lock): Uncovering the principles and performance impact behind it Feb 27, 2024 am 09:00 AM

pythonGIL (Global Interpreter Lock) is an important mechanism in Python. It limits that only one thread can execute Python bytecode at the same time. This is mainly to ensure the stability of the Python interpreter, because Python's memory management and garbage collection mechanisms are single-threaded. If multiple threads are allowed to execute Python bytecode at the same time, memory corruption or other unpredictable errors may result. The principle of GIL is relatively simple. It is a lock maintained by the Python interpreter, and when a thread executes Python bytecode, it acquires the GIL. If other threads want to execute Python bytecode, they must wait for the GIL to be released. When the GIL is released, other

How to use Oracle to query whether a table is locked? How to use Oracle to query whether a table is locked? Mar 06, 2024 am 11:54 AM

Title: How to use Oracle to query whether a table is locked? In Oracle database, table lock means that when a transaction is performing a write operation on the table, other transactions will be blocked when they want to perform write operations on the table or make structural changes to the table (such as adding columns, deleting rows, etc.). In the actual development process, we often need to query whether the table is locked in order to better troubleshoot and deal with related problems. This article will introduce how to use Oracle statements to query whether a table is locked, and give specific code examples. To check whether the table is locked, we

What is the difference between locked and unlocked iPhones? Detailed introduction: Comparison of the differences between locked and unlocked iPhones What is the difference between locked and unlocked iPhones? Detailed introduction: Comparison of the differences between locked and unlocked iPhones Mar 28, 2024 pm 03:10 PM

Apple mobile phones are the most widely chosen mobile phones recently, but we often see people discussing the difference between locked and unlocked Apple mobile phones online, and they are entangled in which one to buy. Today, Chen Siqi will share with you the differences between locked and unlocked iPhones and help you solve problems. In fact, there is not much difference between the two in appearance and function. The key lies in the price and use. What is a locked version and an unlocked version? An iPhone without locking restrictions means that it is not restricted by the operator, and the SIM card of any operator can be used normally. A locked version means that it has a network lock and can only use SIM cards provided by the designated operator and cannot use others. In fact, unlocked Apple phones can use mobile,

Performance comparison of distributed locks implemented by Redis Performance comparison of distributed locks implemented by Redis Jun 20, 2023 pm 05:46 PM

As Internet applications become larger and larger, distributed systems become more and more common. In these systems, distributed locks are an essential feature. Due to the strong demand for distributed locks, there are various implementation methods. Among them, Redis is a popular tool that is widely used in distributed lock implementation. In this article, we will explore the performance comparison of distributed locks implemented by Redis. 1. Basic Concepts of Redis Before discussing the distributed lock performance of Redis, we need to understand some basic concepts of Redis.

How is the lock in golang function implemented? How is the lock in golang function implemented? Jun 05, 2024 pm 12:39 PM

Locks in the Go language implement synchronized concurrent code to prevent data competition: Mutex: Mutex lock, which ensures that only one goroutine acquires the lock at the same time and is used for critical section control. RWMutex: Read-write lock, which allows multiple goroutines to read data at the same time, but only one goroutine can write data at the same time. It is suitable for scenarios that require frequent reading and writing of shared data.

Locks and synchronization in Python concurrent programming: keeping your code safe and reliable Locks and synchronization in Python concurrent programming: keeping your code safe and reliable Feb 19, 2024 pm 02:30 PM

Locks and Synchronization in Concurrent Programming In concurrent programming, multiple processes or threads run simultaneously, which can lead to resource contention and inconsistency issues. To solve these problems, locks and synchronization mechanisms are needed to coordinate access to shared resources. Concept of Lock A lock is a mechanism that allows only one thread or process to access a shared resource at a time. When one thread or process acquires a lock, other threads or processes are blocked from accessing the resource until the lock is released. Types of locks There are several types of locks in python: Mutex lock (Mutex): ensures that only one thread or process can access resources at a time. Condition variable: Allows a thread or process to wait for a certain condition and then acquire the lock. Read-write lock: allows multiple threads to read resources at the same time, but only allows one thread to write resources

In-depth analysis of the underlying implementation mechanism of Golang locks In-depth analysis of the underlying implementation mechanism of Golang locks Dec 28, 2023 am 11:26 AM

A detailed explanation of the underlying implementation principles of Golang locks requires specific code examples. Overview: Concurrent programming is a very important part of modern software development, and locks are a mechanism to achieve concurrency control. In Golang, the concept of locks is widely used in concurrent programming. This article will deeply explore the underlying implementation principles of Golang locks and provide specific code examples. The underlying implementation principle of mutex lock (Mutex) Mutex lock is one of the most commonly used lock types in Golang. It uses an underlying data structure sync.M

How to use locks to achieve thread safety in Go language How to use locks to achieve thread safety in Go language Mar 23, 2024 pm 07:00 PM

Using locks to achieve thread safety in Go language With the increasing popularity of concurrent programming, it has become particularly important to ensure safe access of data between multiple goroutines. In the Go language, locks can be used to achieve thread safety and ensure that access to shared resources in a concurrent environment will not cause data competition problems. This article will introduce in detail how to use locks to achieve thread safety in the Go language and provide specific code examples. What is a lock? A lock is a synchronization mechanism commonly used in concurrent programming that can coordinate synchronization between multiple goroutines.

See all articles