自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

MySQL源碼學(xué)習(xí):MDL字典鎖

數(shù)據(jù)庫 MySQL
MDL,Meta Data lock,元數(shù)據(jù)鎖,一般稱為字典鎖。字典鎖與數(shù)據(jù)鎖相對應(yīng)。字典鎖是為了保護數(shù)據(jù)對象被改變,一般是一些DDL會對字典對象改變,如兩個TX,TX1先查詢表,然后TX2試圖DROP,字典鎖就會lock住TX2,知道TX1結(jié)束(提交或回滾)。

什么是MDL

MDL,Meta Data lock,元數(shù)據(jù)鎖,一般稱為字典鎖。字典鎖與數(shù)據(jù)鎖相對應(yīng)。字典鎖是為了保護數(shù)據(jù)對象被改變,一般是一些DDL會對字典對象改變,如兩個TX,TX1先查詢表,然后TX2試圖DROP,字典鎖就會lock住TX2,知道TX1結(jié)束(提交或回滾)。數(shù)據(jù)鎖是保護表中的數(shù)據(jù),如兩個TX同時更新一行時,先得到row lock的TX會先執(zhí)行,后者只能等待。

MDL的設(shè)計目標(biāo)

字典鎖在設(shè)計的時候是為了數(shù)據(jù)庫對象的元數(shù)據(jù)。到達以下3個目的。

1. 提供對并發(fā)訪問內(nèi)存中字典對象緩存(table definatin cache,TDC)的保護。這是系統(tǒng)的內(nèi)部要求。

2. 確保DML的并發(fā)性。如TX1對表T1查詢,TX2同是對表T1插入。

3. 確保一些操作的互斥性,如DML與大部分DDL(ALTER TABLE除外)的互斥性。如TX1對表T1執(zhí)行插入,TX2執(zhí)行DROP TABLE,這兩種操作是不允許并發(fā)的,故需要將表對象保護起來,這樣可以保證binlog邏輯的正確性。(貌似之前的版本存在字典鎖是語句級的,導(dǎo)致 binlog不合邏輯的bug。)

支持的鎖類型

數(shù)據(jù)庫理論中的基本鎖類型是S、X,意向鎖IS、IX是為了層次上鎖而引入的。比如要修改表中的數(shù)據(jù),可能先對表上一個表級IX鎖,然后再對修改的數(shù)據(jù)上一個行級X鎖,這樣就可以保證其他試圖修改表定義的事物因為獲取不到表級的X鎖而等待。

MySQL中將字典鎖的類型根據(jù)不同語句的功能,進一步細(xì)分,細(xì)分的依據(jù)是對字典的操作和對數(shù)據(jù)的操作。細(xì)分的好處是能在一定程度上提高并發(fā)效率,因為如果只定義X和S兩種鎖,必然導(dǎo)致兼容性矩陣的局限性。MySQL不遺余力的定義了如下的鎖類型。

名稱

意義

MDL_INTENTION_EXCLUSIVE

意向排他鎖,只用于范圍上鎖

MDL_SHARED

共享鎖,用于訪問字典對象,而不訪問數(shù)據(jù)。

MDL_SHARED_HIGH_PRIO

只訪問字典對象(如DESC TABLE)

MDL_SHARED_READ

共享讀鎖,用于讀取數(shù)據(jù)(如select)

MDL_SHARED_WRITE

共享寫鎖,用于修改數(shù)據(jù)(如update)

MDL_SHARED_NO_WRITE

共享非寫鎖,允許讀取數(shù)據(jù),阻塞其他TX修改數(shù)據(jù)(如alter table)

MDL_SHARED_NO_READ_WRITE

用于訪問字典,讀寫數(shù)據(jù)

不允許其他TX讀寫數(shù)據(jù)

MDL_EXCLUSIVE

排他鎖,可以修改字典和數(shù)據(jù)

可以看到MySQL在ALTER TABLE的時候還是允許其他事務(wù)進行讀表操作的。需要注意的是讀操作的事物需要在ALTER TABLE獲取MDL_SHARED_NO_WRITE鎖之后,否則無法并發(fā)。這種應(yīng)用場景應(yīng)該是對一個較大的表進行ALTER時,其他事物仍然可以讀,并發(fā)性得到了提高。

鎖的兼容性

鎖的兼容性就是我們經(jīng)常看到的那些兼容性矩陣,X和S必然互斥,S和S兼容。MySQL根據(jù)鎖的類型我們也可以知道其兼容矩陣如下:

 

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代表不兼容。你可能發(fā)現(xiàn)X和IX竟然兼容,沒錯,其實這里的IX已經(jīng)不是傳統(tǒng)意義上的IX,這個IX是用在范圍鎖上,所以和X鎖不互斥。

數(shù)據(jù)結(jié)構(gòu)

涉及到的和鎖相關(guān)的數(shù)據(jù)結(jié)構(gòu)主要是如下幾個:

MDL_context:字典鎖上下文。包含一個事物所有的字典鎖請求。

MDL_request:字典鎖請求。包含對某個對象的某種鎖的請求。

MDL_ticket:字典鎖排隊。MDL_request就是為了獲取一個ticket。

MDL_lock:鎖資源。一個對象全局唯一。可以允許多個可以并發(fā)的事物同時獲得。

涉及到的源碼文件主要是sql/mdl.cc

鎖資源

鎖資源在系統(tǒng)中是共享的,即全局的,存放在static MDL_map mdl_locks;的hash鏈表中,對于數(shù)據(jù)庫中的一個對象,其hashkey必然是唯一的,對應(yīng)一個鎖資源。多個事務(wù)同時對一張表操作時,申請的 lock也是同一個內(nèi)存對象。獲取mdl_locks中的lock需要通過全局互斥量保護起來 mysql_mutex_lock(&m_mutex); m_mutex是MDL_map的成員。

上鎖流程

一個會話連接在實現(xiàn)中對應(yīng)一個THD實體,一個THD對應(yīng)一個MDL_CONTEXT,表示需要的mdl鎖資源,一個MDL_CONTEXT中包含多個MDL_REQUEST,一個MDL_REQUEST即是對一個對象的某種類型的lock請求。每個mdl_request上有一個ticket對象,ticket中包含lock。

上鎖的也就是根據(jù)MDL_REQUEST進行上鎖。

  1. Acquire_lock:  
  2.     if (mdl_request contains the needed ticket )  
  3.     return ticket;  
  4.     End if;  
  5.     Create a ticket;  
  6.     If (!find lock in lock_sys)  
  7.     Create a lock;  
  8.     End if  
  9.     If (lock can be granted to mdl_request)  
  10.     Set lock to ticket;  
  11.     Set ticket to mdl_request;  
  12.     Else 
  13.     Wait for lock  
  14. End if 

稍微解釋下,首先是在mdl_request本身去查看有沒有相等的或者stronger的ticket,如果存在,則直接使用。否則創(chuàng)建一個 ticket,查找上鎖對象對應(yīng)的lock,沒有則創(chuàng)建。檢查lock是否可以被賦給本事務(wù),如果可以直接返回,否則等待這個lock;

鎖等待與喚醒

字典對象的鎖等待是發(fā)生在兩個事物對同一對象上不兼容的鎖導(dǎo)致的。當(dāng)然,由于lock的唯一性,先到先得,后到的只能等待。

如何判斷一個lock是否可以grant給一個TX?這需要結(jié)合lock結(jié)構(gòu)來看了,lock上有兩個成員,grant和wait,grant代表此 lock允許的事物都上了哪些鎖,wait表示等待的事務(wù)需要上哪些鎖。其判斷一個事物是否可以grant的邏輯如下:

  1. If(compatible(lock.grant, tx.locktype))  
  2.     If (compatible(lock.wait, tx.locktype))  
  3.     return can_grant;  
  4.     End if  
  5. End if 

即首先判斷grant中的鎖類型和當(dāng)前事務(wù)是否兼容,然后判斷wait中的鎖類型和當(dāng)前事務(wù)是否兼容。細(xì)心的話,會想到,wait中的鎖類型是不需要和當(dāng)前事務(wù)進行兼容性比較的,這是不是說這個比較是多余的了?其實也不是,因為wait的兼容性矩陣和上面的矩陣是不一樣的,wait的兼容性矩陣感覺是在 DDL等待的情況下,防止DML繼續(xù)進來(wait矩陣就不寫出來了,大家可以去代碼里看下)。

比如:

TX1                    TX2                    TX3

SELECT T1

DROP  T1

SELECT T1

這時候TX2會阻塞,TX3也會阻塞,被TX2阻塞,也就是說被wait的事件阻塞了,這樣可能就是為了保證在DDL等待時,禁止再做DML了,因為在DDL面前,DML顯得確實不是那么重要了。

如何喚醒被等待的事務(wù)呢?比如喚醒TX2,當(dāng)TX1結(jié)束時,會調(diào)用release_all_locks_for_name,對被鎖住的事務(wù)進行喚醒,具體操作封裝在reschedule_waiters函數(shù)中,重置等待時間的標(biāo)記位進行喚醒,重點代碼如下:

  1. if (can_grant_lock(ticket->get_type(), ticket->get_ctx()))  
  2.     {  
  3.       if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED))  
  4.       {  
  5.         /*  
  6.           Satisfy the found request by updating lock structures.  
  7.           It is OK to do so even after waking up the waiter since any 
  8.           session which tries to get any information about the state of 
  9.           this lock has to acquire MDL_lock::m_rwlock first and thus,  
  10.           when manages to do so, already sees an updated state of the  
  11.           MDL_lock object.  
  12.         */  
  13.         m_waiting.remove_ticket(ticket);  
  14.         m_granted.add_ticket(ticket);  
  15.     } 

今天把mdl系統(tǒng)總體上看了一下,對鎖的請求、等待以及喚醒有了初步了解。并發(fā)性的問題是最難調(diào)試的,大家如果想做鎖方面的實驗,可以利用VS調(diào)試中的凍結(jié)線程的功能,這樣就可以確保并發(fā)情況控制完全按照你設(shè)計思路去呈現(xiàn)。

原文鏈接:http://www.cnblogs.com/nocode/archive/2011/12/15/2289507.html

責(zé)任編輯:林師授 來源: 心中無碼的博客
相關(guān)推薦

2022-03-11 09:12:06

MySQLMDL

2024-01-02 14:17:31

MySQLMDL LOCK語句

2011-08-23 13:56:12

MySQLConnection

2021-02-20 06:09:46

libtask協(xié)程鎖機制

2022-07-20 08:06:57

MySQL表鎖Innodb

2021-07-06 08:37:29

Redisson分布式

2021-03-26 12:07:14

JupyterPython編程語言

2021-06-30 14:56:12

Redisson分布式公平鎖

2021-07-02 08:51:09

Redisson分布式鎖公平鎖

2022-08-12 15:41:11

神經(jīng)網(wǎng)絡(luò)架構(gòu)

2021-07-01 09:42:08

Redisson分布式

2024-11-29 07:38:12

MySQL數(shù)據(jù)庫

2015-01-20 17:09:21

Android源碼手勢鎖

2020-08-24 08:13:25

非公平鎖源碼

2024-04-03 09:50:33

MySQLMDL事務(wù)

2021-07-08 09:21:17

ZooKeeper分布式鎖 Curator

2021-06-27 21:24:55

RedissonJava數(shù)據(jù)

2022-02-08 17:39:04

MySQL服務(wù)器存儲

2011-04-22 14:14:21

MySQL偷窺線程

2010-11-22 14:27:05

MySQL鎖表
點贊
收藏

51CTO技術(shù)棧公眾號