MySQL online DDL


1.1 Online DDL語法

online DDL是在mysql5.6版本后加入的特性,語法:

加列
alter table 表名 add column 列名 數據類型,ALGORITHM 算法;
例如:
alter table t3 add column name1 varchar(16),ALGORITHM INPLACE/COPY/DEFAULT;
可以不指定算法:
alter table t3 add column name1 varchar(16);

加索引:
alter table 表名 add index 索引名(列名),ALGORITHM INPLACE;
例如:
alter table t3 add index idx_name(name1) , ALGORITHM INPLACE/COPY/DEFAULT;
可以不指定算法:
alter table t3 add index idx_name(name1);

注:copy是offline的。 默認情況下不需要指定算法,系統會自主選擇 。

1.2 online DDL(copy)

1.2.1 copy

alter table sbtest1 add column c varchar(122), ALGORITHM=COPY;
1.2.2 copy方式三個階段
准備階段->執行階段->提交階段

1.2.2.1 准備階段(prepare階段)
1.對元數據進行添加共享鎖(MDL-S)[Meta Data Lock Share],讀取原表結構。(不能進行DDL,不阻塞DML,但是過程很短)
2.S鎖升級為X鎖(共享鎖升級為排他鎖),此時阻塞DDL、DML。
3.創建和原表一致的臨時表。server層會執行類似create table的語句來創建一個和表結構一致的臨時表,在引擎層也會生成frm和ibd文件。
1.2.2.2 執行階段 (run)
4.修改新創建的臨時表的表結構。
5.臨時表的表結構修改完成之后,server層copy原來表數到到臨時表中(阻塞DML,阻塞的時間取決於拷貝的速度)表一旦過大,受拷貝數據到臨時表的影響。
6.server層替換兩個表(重命名臨時表及文件),修改原來的文件,然后然后將臨時文件名修改成原文件名。
7.刪除原表所有數據。
1.2.2.3 提交階段 (commit)

8.commit,釋放所有鎖。

1.2.3 注意

1.從開始,一直到執行結束,都是上鎖(MDL-X)的,阻塞所有的DDL和修改類的DML,大多數情況下SELECT操作不會被阻塞。
2.此類操作不是online DDL,在執行整個DDL階段(執行階段)都是阻塞業務的。

1.3 online DDL(inplace)

1.3.1 執行原理

三階段:准備階段 -> 執行階段 -> 提交階段
inplace原理:整個過程都是阻塞其他DDL (inplace 5.6開始支持,把執行流程下推到了引擎層執行),如圖:
image

1.3.2 inplace三階段

1.3.2.1 准備階段(prepare階段)
准備階段阻塞DML
0.在進入prepare階段前對元數據持有可升級的S鎖(MDL-S鎖),在此階段不允許DML, 不允許部分ddl,例如:drop操作。
1.在預備階段MDL-S鎖會升級為X鎖(排他鎖),在此時會判斷,操作是否需要rebuild table。 
2.判斷是需要rebuild table還是no rebuild table,判斷完之后進行下一步,如果需要rebuild table,則申請row log空間。

row log作用:記錄online DDL執行階段,對原表數據做的DML操作的。(row log由innodb_sort_buffer_size決定)。
如果需要rebuild table,則需要在engine層生成原表的轉儲文件(比如:ibd,frm文件,DDL階段執行)。
如果是no reduild table,則要在engine層則只需要生成frm文件(比如加索引就是no rebuild table,只需要生成frm,DDL階段執行。

1.3.2.2 執行階段 (run)
DDL執行階段不阻塞DML 。
3.執行階段 會把X鎖降級為S鎖,該階段不阻塞dml操作 ,這個階段被稱為online階段,例如在加列過程中可能時間比較長,在這期間大部分時間是不阻塞DML操作
4.MDL-X鎖降級為MDL-S鎖,將原表存儲的數據讀取到prepare階段創建的ibd文件中(engine層完成,直接分析數據頁,內部結構,將原表的數據記錄逐行取出后進行處理,且會執行ddl修改表結構,並應用到新的ibd文件中)
1.3.2.3 提交階段
commit階段阻塞DML
5.提交階段engine層應用row log中的操作到新的ibd文件中直到最后一個,系統會自動判斷進行截斷,避免源源不斷的DML操作。
6.此時MDL-S鎖再此升級到MDL-X鎖(拒絕所的DML),然后把row log中剩余的數據應用完。
7.刪除原表,替換新表為原表( 最后將臨時文件替換為原文件,清理老文件)。
8.最后提交。

1.4 一些疑問

1.4.1.Online DDL會不會鎖表?

用戶角度看online ddl,在執行ddl期間,不阻塞DML操作。
管理員角度看online ddl
准備階段 持有X鎖      ->阻塞DML
執行階段 降級為S鎖    ->不阻塞DML
提交階段 升級為X鎖    ->阻塞DML

1.4.2支持 INPLACE 算法的 DDL 一定是 Online 的嗎?

不一定,從三個階段看:copy和inplace(第一、第三階段對用戶來說就不是online的,第二階段對用戶來講是online的)。
COPY 算法執行的 DDL肯定不是 Online 的。
INPLACE 算法執行的 DDL 不一定是 Online 的。

1.4.3 online ddl需不需要額外的磁盤空間?

對於engine層需要創建ibd轉儲文件的操作,是需要額外的存儲空間,所以操作的時長,是受到數據量的影響,但不會阻塞業務

1.4.4 copy方式和inplace方式的區別?

copy是在server層,inlpace是在engine層。
1.4.5 如何判斷是rebuild table還是no rebuild table?
可以觀察ddl執行時間和快慢,以一張大表為例:

方法1:如果是rebuild table方式,在執行階段會很慢。
方法2:可以觀察數據目錄下是否生成文件如:#sql_xxx.ibd/frm(主要是ibd文件)且會持續增大

1.4.6 如何判斷是否online DDL?

mysql> alter table sbtest1 modify column c varchar(121);
Query OK, 5000 rows affected (0.28 sec)  # 如果不是0 rows 則是offline DDL

mysql> alter table sbtest1 modify column c varchar(122);
Query OK, 0 rows affected (0.00 sec)    # 如果是0 rows affected 則是online DDL
Records: 0  Duplicates: 0  Warnings: 0

1.5 小結

1.加索引DDL,受一定原表數據的影響,加列會DDL受原表數據影響。
2.稱直為inplace是因為不涉及到server層的操作,而且直接在engine層直接做inplace轉換。
3.在prepare階段和commit階段少量時間加鎖,其中在執行DDL階段是online的,所以在ddl階段不管執行了多長時間,對原有業務的DML操作不會有影響,不阻塞,在負載、IO上可能會有點影響 。
4.inplace中,不需要通過server層的create語句重建表,但是依然需要在engine層,生成ibd轉儲文件,所以需要做此步驟的操作(如:加列),依然需要額外的存儲空間。可以理解為,之所以稱inplace,其實是將操作下推到engine層去執行。
5.更多online DDL,請查看:https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html


免責聲明!

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



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