Inhaltsverzeichnis
什么是MDL
MDL的设计目标
支持的锁类型
锁的兼容性
数据结构
Heim Datenbank MySQL-Tutorial MySQL源码学习――MDL字典锁_MySQL

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

Jun 01, 2016 pm 01:44 PM
Ja

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
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Was ist der Unterschied zwischen gesperrten und entsperrten iPhones? Ausführliche Einführung: Vergleich der Unterschiede zwischen gesperrten und entsperrten iPhones Was ist der Unterschied zwischen gesperrten und entsperrten iPhones? Ausführliche Einführung: Vergleich der Unterschiede zwischen gesperrten und entsperrten iPhones Mar 28, 2024 pm 03:10 PM

Apple-Handys sind in letzter Zeit das von den Menschen am häufigsten gewählte Mobiltelefon, aber wir sehen oft, dass Leute online über den Unterschied zwischen gesperrten und entsperrten Apple-Handys diskutieren und sich nicht sicher sind, welches sie kaufen sollen. Heute verrät Ihnen Chen Siqi den Unterschied zwischen gesperrten und entsperrten iPhones und hilft Ihnen bei der Lösung von Problemen. Tatsächlich gibt es zwischen den beiden keinen großen Unterschied in Aussehen und Funktion. Der Schlüssel liegt im Preis und in der Verwendung. Was ist eine gesperrte Version und eine entsperrte Version? Ein iPhone ohne Sperrbeschränkungen bedeutet, dass es nicht durch den Betreiber eingeschränkt wird und die SIM-Karte jedes Betreibers normal verwendet werden kann. Eine gesperrte Version bedeutet, dass sie über eine Netzwerksperre verfügt und nur die vom angegebenen Betreiber bereitgestellte SIM-Karte und keine anderen verwenden kann. Tatsächlich können entsperrte Apple-Telefone mobile,

Wie frage ich mit Oracle ab, ob eine Tabelle gesperrt ist? Wie frage ich mit Oracle ab, ob eine Tabelle gesperrt ist? Mar 06, 2024 am 11:54 AM

Titel: Wie kann ich mit Oracle abfragen, ob eine Tabelle gesperrt ist? In der Oracle-Datenbank bedeutet Tabellensperre, dass, wenn eine Transaktion einen Schreibvorgang für die Tabelle ausführt, andere Transaktionen blockiert werden, wenn sie Schreibvorgänge für die Tabelle ausführen oder strukturelle Änderungen an der Tabelle vornehmen möchten (z. B. Spalten hinzufügen, Zeilen löschen). , usw.). Im eigentlichen Entwicklungsprozess müssen wir häufig abfragen, ob die Tabelle gesperrt ist, um damit verbundene Probleme besser beheben und beheben zu können. In diesem Artikel wird erläutert, wie Sie mithilfe von Oracle-Anweisungen abfragen, ob eine Tabelle gesperrt ist, und es werden spezifische Codebeispiele aufgeführt. Um zu überprüfen, ob der Tisch gesperrt ist, haben wir

Python GIL (Global Interpreter Lock): Aufdecken der Prinzipien und Auswirkungen auf die Leistung dahinter Python GIL (Global Interpreter Lock): Aufdecken der Prinzipien und Auswirkungen auf die Leistung dahinter Feb 27, 2024 am 09:00 AM

PythonGIL (Global Interpreter Lock) ist ein wichtiger Mechanismus in Python. Er begrenzt, dass nur ein Thread gleichzeitig Python-Bytecode ausführen kann. Dies dient hauptsächlich dazu, die Stabilität des Python-Interpreters sicherzustellen, da die Speicherverwaltungs- und Garbage-Collection-Mechanismen von Python Single-Threaded sind. Wenn mehrere Threads gleichzeitig Python-Bytecode ausführen dürfen, kann es zu Speicherbeschädigungen oder anderen unvorhersehbaren Fehlern kommen. Das Prinzip von GIL ist relativ einfach. Es handelt sich um eine Sperre, die vom Python-Interpreter verwaltet wird. Wenn ein Thread Python-Bytecode ausführt, erhält er die GIL. Wenn andere Threads Python-Bytecode ausführen möchten, müssen sie auf die Freigabe der GIL warten. Wenn die GIL freigegeben wird, andere

Wie wird die Lock-in-Golang-Funktion implementiert? Wie wird die Lock-in-Golang-Funktion implementiert? Jun 05, 2024 pm 12:39 PM

Sperren in der Go-Sprache implementieren synchronisierten gleichzeitigen Code, um Datenkonkurrenz zu verhindern: Mutex: Mutex-Sperre, die sicherstellt, dass nur eine Goroutine gleichzeitig die Sperre erhält und zur Steuerung kritischer Abschnitte verwendet wird. RWMutex: Lese-/Schreibsperre, die es mehreren Goroutinen ermöglicht, Daten gleichzeitig zu lesen, aber nur eine Goroutine gleichzeitig Daten schreiben kann. Sie eignet sich für Szenarien, die häufiges Lesen und Schreiben gemeinsam genutzter Daten erfordern.

Leistungsvergleich verteilter Sperren, die von Redis implementiert wurden Leistungsvergleich verteilter Sperren, die von Redis implementiert wurden Jun 20, 2023 pm 05:46 PM

Da Internetanwendungen immer umfangreicher werden, werden verteilte Systeme immer häufiger eingesetzt. In diesen Systemen sind verteilte Sperren ein wesentliches Merkmal. Aufgrund der starken Nachfrage nach verteilten Sperren gibt es verschiedene Implementierungsmethoden. Unter diesen ist Redis ein beliebtes Tool, das häufig bei der Implementierung verteilter Sperren verwendet wird. In diesem Artikel untersuchen wir den Leistungsvergleich verteilter Sperren, die von Redis implementiert werden. 1. Grundlegende Konzepte von Redis Bevor wir die verteilte Sperrleistung von Redis diskutieren, müssen wir einige grundlegende Konzepte von Redis verstehen.

Sperren und Synchronisierung in der gleichzeitigen Python-Programmierung: So bleibt Ihr Code sicher und zuverlässig Sperren und Synchronisierung in der gleichzeitigen Python-Programmierung: So bleibt Ihr Code sicher und zuverlässig Feb 19, 2024 pm 02:30 PM

Sperren und Synchronisierung bei der gleichzeitigen Programmierung Bei der gleichzeitigen Programmierung werden mehrere Prozesse oder Threads gleichzeitig ausgeführt, was zu Ressourcenkonflikten und Inkonsistenzproblemen führen kann. Um diese Probleme zu lösen, sind Sperren und Synchronisationsmechanismen erforderlich, um den Zugriff auf gemeinsam genutzte Ressourcen zu koordinieren. Konzept der Sperre Eine Sperre ist ein Mechanismus, der jeweils nur einem Thread oder Prozess den Zugriff auf eine gemeinsam genutzte Ressource ermöglicht. Wenn ein Thread oder Prozess eine Sperre erhält, wird der Zugriff anderer Threads oder Prozesse auf die Ressource blockiert, bis die Sperre aufgehoben wird. Arten von Sperren Es gibt verschiedene Arten von Sperren in Python: Mutex-Sperre (Mutex): stellt sicher, dass jeweils nur ein Thread oder Prozess auf Ressourcen zugreifen kann. Bedingungsvariable: Ermöglicht einem Thread oder Prozess, auf eine bestimmte Bedingung zu warten und dann die Sperre zu erhalten. Lese-/Schreibsperre: Ermöglicht mehreren Threads das gleichzeitige Lesen von Ressourcen, erlaubt jedoch nur einem Thread das Schreiben von Ressourcen

Eingehende Analyse des zugrunde liegenden Implementierungsmechanismus von Golang-Sperren Eingehende Analyse des zugrunde liegenden Implementierungsmechanismus von Golang-Sperren Dec 28, 2023 am 11:26 AM

Eine detaillierte Erläuterung der zugrunde liegenden Implementierungsprinzipien von Golang-Sperren erfordert spezifische Codebeispiele. Übersicht: Gleichzeitige Programmierung ist ein sehr wichtiger Teil der modernen Softwareentwicklung, und Sperren sind ein Mechanismus zur Erzielung einer Parallelitätskontrolle. In Golang wird das Konzept der Sperren häufig in der gleichzeitigen Programmierung verwendet. In diesem Artikel werden die zugrunde liegenden Implementierungsprinzipien von Golang-Sperren eingehend untersucht und spezifische Codebeispiele bereitgestellt. Das zugrunde liegende Implementierungsprinzip der Mutex-Sperre (Mutex) Die Mutex-Sperre ist einer der am häufigsten verwendeten Sperrtypen in Golang. Es verwendet eine zugrunde liegende Datenstruktur sync.M

Verwendung und Best Practices von Cache-Sperren in Golang. Verwendung und Best Practices von Cache-Sperren in Golang. Jun 20, 2023 am 09:50 AM

Verwendung und Best Practices von Cache-Sperren in Golang. Cache-Sperren in Golang sind eine Methode zur Verbesserung der Ausführungseffizienz in Umgebungen mit hoher Parallelität. In einer gleichzeitigen Umgebung können mehrere Goroutinen gleichzeitig auf dieselben Daten zugreifen, was zu Problemen wie Sperrkonkurrenz und Datenkonkurrenz führen kann. Cache-Sperren sind ein Mechanismus zur Verwaltung der gemeinsamen Datenspeicherung, um die Datenintegrität und -konsistenz sicherzustellen, indem gleichzeitiger Zugriff verhindert wird. In diesem Artikel konzentrieren wir uns auf die Verwendung und Best Practices von Cache-Sperren in Golang. 1.Gol

See all articles