MySQL5 5加主鍵鎖讀問題 續

2021-09-22 20:33:30 字數 1188 閱讀 8501

背景

說到mysql 5.5加主鍵導致阻塞源表的讀的問題。

有同學提到從呼叫函式看,在預設的old_alter_table=off的情況下,加主鍵過程沒有看到copy to tmp table。

這裡我們再細說一下。

說說fast index creation

在mysql 5.1以後innodb引入了fast index creation。在有這個feature之前,mysql認為所有的加減索引操作都必須建立臨時表、拷貝資料、刪除源表。

有了這個神奇的功能之後,innodb跟mysql說,稍等,要是加索引,不要你拷貝資料了,「放著我來」。怎麼作的呢?

1)       掃瞄源表,將每行中用於索引的字段取出來

2)       排序構造新索引

3)       插入源表中

這個就是我們說的inplace-ddl了,大家看到,沒有拷貝新錶的操作。效能因此也提高了。這個過程叫做row_merge_build_indexes。

再說說加主鍵

對於innodb來說,資料也是以索引組織的,因此加主鍵,在概念上說,也是加索引。於是在old_alter_table=off的情況下,mysql照著上面的約定,呼叫row_merge_build_indexes。

那麼innodb是不是在源表加主鍵呢?

這顯然不可能。

fast-index-creation的精髓是只需要讀主鍵資料,生成新索引插入到源表中。若加的是主鍵,說明原來沒有定義主鍵(多麼正確的廢話),這時候innodb是使用系統分配的row_id作為主鍵。當我們增加主鍵以後,不可能「構造主鍵,插入源表」----那樣就倆主鍵了。。。

原始碼實現

實際上row_merge_build_indexes有兩個引數(old_table, new_table)。

若新增的索引中不包含主鍵,則new_table == old_tablie,否則不等。

對於不等的情況,這個過程就變成

1)       掃瞄old_table主鍵上的資料

2)       按照新增的索引插入到new_table中

3)       

而由於「主鍵」索引的葉子節點,實際上是包含所有資料,所以這個過程,其實就是

copy table。

對於new_table!=old_table的情況,在拷貝資料期間只需要加共享鎖即可,只是5.5下沒有意識到這個問題而已。

MySQL5 5加主鍵鎖讀問題

背景 有同學討論到mysql 5.5下給大表加主鍵時會鎖住讀的問題,懷疑與fast index creation有關,這裡簡單說明下。對照現象 為了說明這個問題的原因,有興趣的同學可以做對比實驗。1 在給innodb表建立主鍵期間,會鎖住該錶上的讀資料 2 但是同樣的表執行刪除主鍵期間,不會鎖住該錶...

MySQL5 5加主鍵鎖讀問題

mysql5.5加主鍵鎖讀問題 背景 有同學討論到mysql 5.5下給大表加主鍵時會鎖住讀的問題,懷疑與fast index creation有關,這裡簡單說明下。對照現象 為了說明這個問題的原因,有興趣的同學可以做對比實驗。1 在給innodb表建立主鍵期間,會鎖住該錶上的讀資料 2 但是同樣的...

mysql5 5 遇到的路徑問題

下面是my.ini裡面的引數 basedir c program files mysql mysql server 6.0 datadir 存放表結構的路徑 innodb data home dir 這個是存放表資料的路徑 ibdata1 存放表資料 你應該是使用的innodb,檢查你的my.cnf...