1. 程式人生 > >關於MySQL建表對DML的影響

關於MySQL建表對DML的影響

今天一位同學問到線上曾經碰到過連續建表,導致阻塞普通的insert、update等。不過也沒有保留現場。因此有疑問為什麼建表會影響DML?

分析

首先這個現象不是在所有場景都會碰到(否則MySQL的使用者們早就跳起來了)。

一來建表這個操作本身很快,只涉及到寫表定義檔案和初始化表空間。中間涉及到redo和undo的操作也很少(這裡只討論InnoDB表)。因此除非碰到磁碟IO響應不了,否則多數情況下建表操作很快結束,不會“穩定復現”

二來即使由於io原因,建表過程執行時間較長,建表操作也不會阻塞一些DML操作。

         因此只能從程式碼出發看衝突的case。

         假設session 1正在執行一個create table操作,且由於io原因阻塞在寫表空間檔案這個步驟上。討論session2作如下操作的場景。

無主鍵表insert

此時insert操作由於需要申請系統自增主鍵,需要對dict_sys->mutex加鎖。而這個鎖需要等session1建表操作完成後才釋放,因此出現等待。

有外來鍵表的操作

此時session2需要判斷外來鍵一致性,需要對dict_sys->mutex加鎖。

         這裡包含幾個方面:外來鍵約束的child表插入資料時和parent表刪除資料時,已經這兩個表的關聯外來鍵欄位被修改時,均會觸發等待。

有同學會說我們線上這兩種情況都禁止了,是不是就不會因為這個鎖的原因導致阻塞dml?

新開啟表時

若這個insert操作需要新開啟一個表時,需要根據表名從字典中取出資訊,也會觸發等待。

         即使原來已經開啟過的表,也會因為執行了flush table或者表空間淘汰而要求下次訪問需要重新開啟。

影響的其他操作

順著dict_sys->mutex我們還可以發現有以下幾個操作,若發生在session2,都會被阻塞

1)                 1) Flush tables

2)                    select * from information_schema.tables;

        2) 以上兩個因為都要訪問到表物件列表,還比較好理解

3)                 select * from information_schema.innodb_sys_tables;

       3)實際上可以用另外一個鎖來單獨處理sys_tables

4)                  show create table another_table

    這個是因為必須判斷是否有外來鍵關聯

         簡單留個問題:為什麼show tables並不會被阻塞?