mysql metadata lock(一)


      想必玩過mysql的人對Waiting for table metadata lock肯定不會陌生,一般都是進行alter操作時被堵住了,導致了我們在show processlist 時,看到線程的狀態是在等metadata lock。本文會對mysql 的metadata lock做一個小小的總結,希望對大家有所幫助。

     MDL是在5.5才引入到mysql,之前也有類似保護元數據的機制,只是沒有明確提出MDL概念而已。但是5.5之前版本(比如5.1)與5.5之后版本在保護元數據這塊有一個顯著的不同點是,5.1對於元數據的保護是語句級別的,5.5對於metadata的保護是事務級別的。所謂語句級別,即語句執行完成后,無論事務是否提交或回滾,其表結構可以被其他會話更新;而事務級別則是在事務結束后才釋放MDL。

     引入MDL后,主要解決了2個問題,一個是事務隔離問題,比如在可重復隔離級別下,會話A在2次查詢期間,會話B對表結構做了修改,兩次查詢結果就會不一致,無法滿足可重復讀的要求;另外一個是數據復制的問題,比如會話A執行了多條更新語句期間,另外一個會話B做了表結構變更並且先提交,就會導致slave在重做時,先重做alter,再重做update時就會出現復制錯誤的現象。

     5.5以后,什么情況下會碰到MDL鎖,我結合實際情況舉3個會出現MDL的場景,來分析MDL加鎖時機。下文的.測試都是以mysql 5.5這個版本為基准,沒有考慮到online ddl,下一篇博文會詳細介紹5.6的online ddl。

1.大查詢或mysqldump導致alter等待MDL

時間點

會話A

會話B

會話C

1

Select count(*) from t;

 

 

2

 

alter table t add column c3 int;

 

3

 

 

Show processlist;

B:copy to tmp table

4

 

 阻塞

Show processlist;

B:Waiting for table metadata lock

 

5

 A:執行完畢

 

 

6

 

 

Show processlist; 

B:rename table

7

Select count(*) from t;

 

 

8

 

 B:執行完畢

 

9

 

 

Show processlist;

 

A: Sending data

 

10

A:執行完畢

   

                                                                                                  表1

       從表1可以看到,會話A先執行select ,B后執行alter,在會話A執行完畢前,會話B拿不到MDL鎖,從表格上面來看,主要阻塞在rename階段。A會話在時間點5執行完畢后,會話B拿到MDL鎖,變為rename table狀態,這個操作持續時間非常短,時間點7,A會話再次執行查詢,當B執行完后,此時A正常執行。這說明對於MDL鎖而言,select會阻塞alter,而alter不會阻塞select。在rename的瞬間,alter是會阻塞select的,詳細請參考《mysql metadata lock(二)》

2.表上存在未提交的事務,導致alter等待MDL

時間點

會話A

會話B

會話C

1

set autocommit=0;

update t set c2='9999' where c1=4;

 

 

2

 

alter table t drop column c3;

 

3

 

 

Show processlist;

B:Waiting for table metadata lock

4

A:提交事務

commit

 

 

5

 

 

Show processlist;

B:copy to tmp table

6

 

B:繼續執行

 

7

update t set c2='9999' where c1=4;阻塞

 

 

8

 

 

Show processlist;

A: Waiting for table metadata lock

B: copy to tmp table

9

 

B執行完畢

 

10

A執行完畢

 

 

                                                                                                  表2

       從表2可以看到,會話A第一次執行update語句后,未提交,導致后面會話B執行alter語句時需要等待MDL鎖;時間點4,A會話提交事務,此時會話B獲取MDL鎖,開始執行;時間點7,A會話再次發起update操作,此時A會話被阻塞住,這說明對於MDL鎖而言,update會阻塞alter,同樣alter也會阻塞update。

PS:時間點3由於通過show processlist只看到alter被阻塞了,但不清楚被誰阻塞,可以通過查看information_schema.innodb_trx可以找到活動的事務。

3.這種情況是第1種情況的特例,存在一個查詢失敗的語句,比如查詢不存在的列,語句失敗返回,但是事務沒有提交,此時alter仍然會被堵住。

時間點

會話A

會話B

會話C

1

Start transaction;

Select c99 from t;

Unknown column 'c99' in 'field list'

 

 

2

 

alter table t drop column c3;

 

3

 

 

Show processlist;

B:copy to tmp table

4

 

 

Show processlist;

B:Waiting for table metadata lock

5

A:提交事務

commit

 

 

6

 

執行完畢

 

                                                                                                表3

      這里注意時間1,會話A要顯示開啟一個事務,否則查詢會隱式回滾結束,無法重現上面的場景。會話B執行alter后,沒有立即阻塞住,而是立馬開始copy to tmp table,這個過程結束后,才進行了MDL鎖等待。這怎么解釋呢,應該是執行alter操作主要分為創建臨時新表->插入老表的數據->臨時新表rename to老表三個步驟,在這種情況下,到最后一步才需要MDL鎖,所以copy過程中不會阻塞。由於沒有查詢在進行,而且查詢也沒有進入innodb層 (失敗返回),所以show processlist和information_schema.innodb_trx沒有可以參考的信息。

     這里有一個小疑點,對於第二種情況,alter在開始時就立馬堵住了,第一種和第三種情況是copy結束后,才堵住。通過多次實驗,確實發現第二種情況在opening tables就堵住了。為什么要這樣具體原因還沒弄清楚,有興趣的同學可以去debug源碼看看究竟。

root@chuck 11:57:41>show profile for query 4;
+----------------------+-----------+
| Status | Duration |
+----------------------+-----------+
| starting | 0.000050 |
| checking permissions | 0.000004 |
| checking permissions | 0.000005 |
| init | 0.000007 |
| Opening tables | 19.068828 |
| System lock | 0.000011 |
| setup | 0.000034 |
| creating table | 0.005047 |
| After create | 0.000056 |
| copy to tmp table | 89.574539 |
| rename result table | 1.101672 |
| end | 0.000040 |
| query end | 0.000004 |
| closing tables | 0.000009 |
| freeing items | 0.000021 |
| logging slow query | 0.000002 |
| logging slow query | 0.000090 |
| cleaning up | 0.000004 |
+----------------------+-----------+

 

參考:

http://www.mysqlperformanceblog.com/2013/02/01/implications-of-metadata-locking-changes-in-mysql-5-5/

http://ctripmysqldba.iteye.com/blog/1938150

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM