【MySQL】MetaDataLock之一

北在南方發表於2016-04-13
一 簡介
 和MySQL打交道比較多的朋友,肯定遇到過 “Waiting for table metadata lock”或者由於MDL導致的故障,不過本文介紹MDL鎖之前 我們先看一個著名的bug#989 大致情況如下:
 s1:
  BEGIN;
  INSERT INTO t … ;
  COMMIT;
 s2:
  DROP TABLE t;
然後上面的操作流程在binlog記錄的順序是 
 DROP TABLE t;
 BEGIN;
  INSERT INTO t … ;
 COMMIT;
很顯然備庫執行binlog時會先刪除表t,然後執行insert 會報1032 error,導致複製中斷。為了解決該bug,MySQL 在5.5.3引入了MDL鎖。
二  metadata lock是什麼

  顧名思義,metadata lock即後設資料鎖。在資料庫中後設資料即資料字典資訊包括db,table,function,procedure,trigger,event等。metadata lock主要為了保證後設資料的一致性,用於處理不同執行緒操作同一資料物件的同步與互斥問題,如:


s1: begin select * from t1 for update ... 
 
s2: begin alter table t1 add column str varchar(30) 

 在以上兩個事務中,s1 s2都會操作表t1,但由於s1首先獲取t1的鎖,而s2在獲得鎖的時候由於互斥,所以只能等待;
  其實5.5也有類似保護後設資料的機制,只是沒有明確提出MDL概念而已。但是5.5之前版本(比如5.1)與5.5之後版本在保護後設資料這塊有一個顯著的不同點是,5.1對於後設資料的保護是語句級別的,5.5對於metadata的保護是事務級別的。所謂語句級別,即語句執行完成後,無論事務是否提交或回滾,其表結構可以被其他會話更新;而事務級別則是在事務結束後才釋放MDL。引入MDL後,主要解決2個問題 
事務隔離問題,比如在可重複隔離級別下,會話A在2次查詢期間,會話B對錶結構做了修改,兩次查詢結果就會不一致,無法滿足可重複讀的要求.
資料複製問題,比如會話A執行了多條更新語句期間,另外一個會話B做了表結構變更並且先提交,就會導致slave在重做時,先重做alter,再重做update時就會出現複製錯誤的現象。也就是簡介中提到的bug。

三 小結
   
   MySQL引入MDL之後 也會帶來一定的負面影響  比如 “wait for global read lock”或者“wait for table lock”之類的鎖等待,當遇到大查詢,同時遇到一個DDL ,基本能造就一個故障了。後面的文章會深入介紹MDL的實現原理和執行機制,加入一些常見的案例和解決方法。


相關文章