MySQL5.5加主鍵鎖讀問題

背景ide

有同窗討論到MySQL 5.5下給大表加主鍵時會鎖住讀的問題,懷疑與fast index creation有關,這裏簡單說明下。spa


對照現象線程

爲了說明這個問題的緣由,有興趣的同窗能夠作對比實驗。blog

   1)  在給InnoDB表建立主鍵期間,鎖住該表上的讀數據索引

   2) 可是一樣的表執行刪除主鍵期間,不會鎖住該表上的讀操做get

----這說明與是否fast index creation無關,由於這兩個操做在數據層面的行爲應該是相似的,實際上,建立/刪除主鍵都必須copy datait


   3) 在建立主鍵期間,鎖住該表上執行的show create tableio

----13的現象能夠猜想出,實際上與meta data lock有關。table


關於meta data lock(MDL)ast

MySQL 5.5中引入了MDL,當須要訪問、修改表結構時,都須要對meta data加鎖(讀或寫)。好比,當一個線程須要修改表結構的任意一部分時,此時須要阻塞對錶結構的訪問,固然也須要阻塞對數據行的訪問。


加主鍵流程

當對一個表做加主鍵操做時,大體流程以下

       1) MDL加寫鎖

      2) 操做數據,最耗時部分,注意須要copy data,所以流程上是

            a)建立一個臨時表A,表A定義爲修改後的表結構

            b)從原表讀取數據插入表A

            c)刪除原表,將表A重命名爲原表名

      3)  MDL釋放寫鎖


從這個流程能夠看到,在最耗時的部分,meta data是被一個X鎖保護的。所以在此期間,show create table或者select data都是會被阻塞。


這解釋了上面的1) 3)


刪除主鍵流程

       1)  MDL加讀鎖

      2)  操做數據,最耗時部分

            a) 建立一個臨時表A,表A定義爲修改後的表結構

            b) 從原表讀取數據插入表A

       3) MDL將讀鎖升級爲寫鎖

           c) 刪除原表,將表A重命名爲原表名

      4)  MDL釋放寫鎖


  這個在最耗時的數據操做部分,加的是MDL的讀鎖,這樣不會影響訪問原表的表結構或數據(固然要作更新是不行的)。而最後升級爲寫鎖的時間,只是作重命名錶的操做,阻塞的時間就很短。


結論

         1) 顯然第二個流程更合理

       2) 這個能夠認爲是MySQL一個可改進的點,而且在5.6下已經改進

       3) 這個問題與是copy data仍是inplace方式執行DDL無關,實際上因爲InnoDB的彙集索引組織結構,增、刪主鍵都是必須得copy data的。


==========更新====

有同窗問說爲何在5.5 set old_alter_table=on;以後是不會阻塞讀的? 由於打開old_alter_table以後,MySQL認爲此次不管如何是要copy data的,因此鎖用的是「刪除主鍵流程」的策略。


實際上不管old_alter_table是否打開,對主鍵操做都是必須copy data的,5.6的改進就是基於這個判斷。


轉自:http://dinglin.iteye.com/blog/1884696

相關文章
相關標籤/搜索