mysql鎖系列之MDL元資料鎖之二

2021-09-11 21:34:26 字數 3148 閱讀 8374

基礎材料:

centos7.5  mysql 5.7.24

session108

session109

session110

session111

session112

session113

session114

session115

session116

begin;

lock tables testok write;

lock tables testok read;

alter table testok add p varchar(10);

begin;

lock tables testok write;

lock tables testok read;

alter table testok add pp varchar(10);

begin;

select * from testok;

select * from testok;

select * from testok;

按照之前的理論推算(以下鎖均指元資料鎖):

1、目前的情況應該是session108持有該錶的讀鎖,其餘8個session卡住,等待該讀鎖釋放。實際情況符合預期。

2、當session108執行commit後,釋放讀鎖,session109獲取到該錶的寫鎖,剩餘7個session等待該寫鎖釋放。實際情況為session111先執行並提交就沒它什麼事了,然後session109執行,用寫鎖鎖住該錶,然後其餘6個session等待該寫鎖。

3、此時我們在session109上執行unlock tables;顯示釋放寫鎖,根據理論**的結果為session113獲得寫鎖。實際情況符合預期。(此處你可能對session115有疑問,先繼續往下走)

4、在session113執行unlock tables;顯示釋放寫鎖,按照理論**結果為session115先執行並提交後,session110\112\114\116同時執行,並持有該錶的讀鎖。實際情況為session110\112\114\116同時執行,並持有該錶的讀鎖,session115等待該讀鎖。

5、為session110\112\114\116釋放讀鎖,session115執行並提交。

可見理論**與結果相差甚遠,為什麼會出現這種情況,下面具體分析一下:

首先在步驟1時,觀察metadata_locks表的情況:

session108持有表讀鎖(shared_read),這個沒什麼問題

session109因為要加寫鎖,期間加了全域性意向排他鎖、資料庫意向排他鎖(granted),這個沒什麼問題。注意第4行,在testok上要加的鎖為(shared_no_read_write)(pending),雖然字首為shared,但它實際上是寫鎖。此時要特別注意一下,它pending的原因是在等兩個鎖,乙個是session108的shared_read讀鎖,另乙個是session111的shared_upgradable讀鎖,這也就解釋了為什麼同為寫鎖pending,排他它後面session111反而比它先執行。

session110申請讀鎖,pending了,按照前篇說的,由於session109要加寫鎖,它被阻塞,這個沒什麼問題。

session111因為要加寫鎖,期間加了全域性意向排他鎖、資料庫意向排他鎖(granted)在第8行還對該錶加了shared_upgradable讀鎖,用於online ddl的處理(granted),而在申請表的exclusive排他鎖時,pending了,這個也沒什麼問題。(這裡需要額外說一下shared_upgradable,排隊規則的乙個特例,它並不受前面的寫鎖阻塞依然可以獲得鎖。本身雖然是讀鎖,但同為shared_upgradable會互斥,也就是同一時間一張表上只能存在乙個shared_upgradable讀鎖,這也是為什麼同一時間只有乙個ddl操作能進行),on-line ddl

執行過程還有幾種情況,將在《mysql鎖系列之mdl元資料鎖之三》進行說明。

session112申請讀鎖,pending了。

session113因為要加寫鎖,期間加了全域性意向排他鎖、資料庫意向排他鎖(granted),申請(shared_no_read_write),pending。

session114申請讀鎖,pending了。

session115加了全域性意向排他鎖、資料庫意向排他鎖(granted),申請shared_upgradable讀鎖時,被session111的shared_upgradable讀鎖互斥

session116申請讀鎖,pending了。

了解了目前所有元資料鎖的情況,我們逐步驗證上面的實際情況:

1、在session108執行commit;,由於session111一直持有shared_upgradable讀鎖,所以session111先拿到寫鎖執行並提交(過程中雖然會降級讀鎖,但其他寫鎖session仍然無法獲得鎖),然後session109執行,用鎖住該錶,然後其餘6個session等待該寫鎖。此時metadata_locks如下:

可以看到目前是session109持有shared_no_read_write寫鎖,session115沒有先執行的原因是他目前在申請讀鎖,優先順序低。

2、 在session109上執行unlock tables;顯示釋放寫鎖,此時metadata_locks如下:

此時session113持有shared_no_read_write寫鎖。

3、在session113上執行,unlock tables;顯示釋放寫鎖,此時metadata_locks如下:

其餘申請讀鎖的session拿到鎖,而session115這個時刻也在申請讀鎖,所以同時拿到shared_upgradable讀鎖,然後再申請寫鎖,此時被其餘seesion阻塞。

至此解釋了元資料鎖的加鎖順序,可以更好的理解元資料鎖加鎖過程**現的一些問題。

注意事項:

MySQL系列之鎖

分布式鎖 疑問?什麼是共享鎖?共享鎖 共享讀鎖,排他鎖 獨佔寫鎖 鎖機制與innodb鎖演算法 在關係型資料庫中,可以按照鎖的粒度把資料庫鎖分為行級鎖 innodb引擎 表級鎖 myisam引擎 和頁級鎖 bdb引擎 myisam採用表級鎖 table level locking innodb支援行...

MySQL原始碼學習 MDL字典鎖

什麼是mdl mdl,meta data lock,元資料鎖,一般稱為字典鎖。字典鎖與資料鎖相對應。字典鎖是為了保護資料物件被改變,一般是一些ddl會對字典物件改變,如兩個tx,tx1先查詢表,然後tx2試圖drop,字典鎖就會lock住tx2,直到tx1結束 提交或回滾 資料鎖是保護表中的資料,如...

Mysql系列之鎖機制

一般乙個程式滿,從消耗的角度,乙個是cpu,乙個是io,但有的時候mysql慢,是因為某條sql不小心把整個表給鎖了。鎖是計算機協調多個程序或執行緒併發訪問某一資源的機制。在資料庫中,除了傳統的計算機資源 如cpu,ram,i o 的爭用外,資料也是供很多使用者共享的資源。如何保證資料併發訪問的一致...