MySQL-添加索引或字段時如何不鎖表


索引的添加MySQL經歷了一下幾個歷程:

一 .在MySQL 5.5版本之前,添加索引具體是這樣的:

1.首先創建一張臨時表和原表數據結構相同,將你要添加的索引加上。

2.把原表數據導入臨時表。

3.刪除原表。

4.將臨時表重命名為原表。

這樣做有很大問題:

首先對於大數據量的導入需要很長的時間,那么在這段時間里新增或修改的數據沒辦法處理。

其次如果碰上大事務正在新增或更新更新這張原表還會鎖表,你還沒辦法用sql去導入到臨時表中。

 

二 .但在InnoDB 1.0版本開始,支持一種Fast Index(快速索引創建)的方式,簡稱FIC,他是這樣做的:

對於輔助索引的創建,他不需要建臨時表,他會直接將原表加S鎖,這樣就不會有數據導入的問題。

但還是會有些其他問題:

這意味着這加索引的這段時間里這張表只能讀,不能增刪改。而且不適用主鍵索引。

 

三. 針對一,二階段的問題,Facebook總結並實現了一種在線執行方案-OSC:

1.初始化,檢查原表所有的問題,包括主鍵,觸發器,外鍵等。

2.創建臨時表,添加索引字段。

3.創建deltas表,為下一步創建觸發器做准備。

4.對原表創建增刪改的觸發器,觸發器產生的草所記錄寫入到上一步創建的deltas表。

5.開始OSC操作的事務。

6.刪除所有輔助索引,再將原表數據通過分片文件寫入臨時表。

7.將deltas表中產生的記錄應用到臨時表中。

8.重新創建輔助索引。

10.將原表和臨時表交換名字,在這個過程中會鎖表,但這個過程很快。

以上便是整個OSC過程,看起來就很復雜,實際的腳本也很復雜,光是核心PHP代碼就2000多行,而且有一定局限性,對於分布式無法主從同步。

 

四.MySQL5.6版本開始支持在線創建--Online DDL,只需一行代碼:

以下是對輔助索引的添加:

 ALTER TABLE table_name ADD INDEX  indea_name ,ALGORITHM=INPLACE,LOCK=NONE;

ALGORITHM指定創建或刪除索引得算法,有以下幾類:

COPY:按照5.1之前的版本,創建臨時表的方式。

INPLACE:不需要創建臨時表。

DEFAULT:表示根據參數old_alter_table來判斷是用COPY還是INPLACE,默認OFF,表示采用INPLACE方式。

 

 

 LOCK表示加鎖情況:

NONE:不添加任何鎖,允許並發。

SHARE:加S鎖。

EXCLUSIVE:加X鎖,讀寫都不允許。

DEFAULT:會先判斷是否可用NONE,若不能再判斷是否可用SHARE模式,最后判斷EXCLUSIVE。

Online DDL的原理是則好樣的:

1.在創建或刪除索引的同時,會將這段時間發生的增刪改操作的日志寫入一個緩存中,待完成索引后再重新將日志應用到表上,達到數據一致性。這個緩存的小由innodb_online_alter_log_max_size控制,默認128MB。可以根據情況調整。

需要注意的是,在這個過程中,sql不會用到正在創建的索引。


免責聲明!

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



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