mysql鎖系列之MDL元數據鎖之二

基礎材料:

centos7.5  mysql 5.7.24


前幾篇博客中介紹了表級鎖(表鎖、元數據鎖)的相關內容,在<mysql鎖系列之MDL元數據鎖之一>簡單說明了一下元數據鎖的優先級爲寫鎖大於讀鎖,同爲寫鎖要排隊。對此我們進行如下測試,按session順序逐個執行語句:

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阻塞。

 4、所有讀鎖session上釋放鎖後,session115成功執行,此時所有鎖消失。


 至此解釋了元數據鎖的加鎖順序,可以更好的理解元數據鎖加鎖過程中出現的一些問題。

注意事項:

SHARED_UPGRADABLE雖然是讀鎖,但其不會被前面的寫鎖阻塞,同爲SHARED_UPGRADABLE會互斥,同一張表同一時間DDL操作不能並行,On-line DDL解決的是DDL與DML之間的並行問題,而不是DDL之間的並行。由於ONLINE DDL 存在三階段過程,還要分幾種情況,下一篇繼續說明。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章