原創做者:黃炎 王悅 周海鳴算法
你們好,本期討論MySQL的DDL,討論的背景是MySQL 8.0+InnoDB。數據庫
DDL(Data Definition Language)數據結構
衆所周知,DDL定義了數據在數據庫中的結構、關係以及權限等。好比CREATE,ALTER,DROP等等。併發
本期咱們討論MySQL 8.0 (使用InnoDB存儲引擎)在修改表結構時,究竟會發生什麼?運維
DDL與表結構ui
既然DDL的做用是改變表結構,那表結構在InnoDB引擎中是什麼樣的呢?如上圖,邏輯上,InnoDB表中的數據能夠理解成按照主鍵(聚簇索引)順序存放的,每一行的數據依次排列 (物理上,InnoDB表中的數據按照InnoDB的數據結構B+樹進行排列)。spa
當須要對錶增長一列時,會涉及到每一行數據排列的變更,須要重建整張表的數據,可想而知這種變更的成本是高昂的。3d
然而並非每一種DDL都要付出這麼大的成本,要看具體的分類。日誌
MySQL 8.0 將DDL用如下五個維度分類討論:code
Instant:此變動能夠"馬上"完成
In Place:此變動由InnoDB引擎獨立完成,不須要使用Redo log等,能夠節省開銷
Rebuild Table:此變動會重建聚簇索引,通常狀況下,涉及到數據變動時才須要重建聚簇索引
Permits Concurrent DML:此變動進行時,是否容許其餘DML變動同一張表。此特性關係到變動是否會長時間阻塞業務。
Only Modifies Metadata:此變動是否只變動元信息,不涉及數據變動。
爲了容易理解DDL的分類,下圖中,咱們窮舉了MySQL DDL文檔中的分類。
列出了這五個維度的每種組合狀況,每種狀況中分別挑選一例典型進行討論。如下分類是按照DDL的成本從低到高排序。
e.g. ALTER TABLE `t1` ALTER COLUMN `c1` SET DEFAULT '1';
修改列的默認值不須要變更已有的數據頁,僅須要修改表的元信息便可,因此這是成本最低的一種狀況,能夠"馬上"完成。
e.g. ALTER TABLE `t1` DROP INDEX `idx1`;
刪除二級索引除了修改表的元信息以外,須要將對應的二級索引標記爲刪除狀態,由於不須要真的刪除,僅僅設置標記量,因此這仍然是一種成本較低的狀況。 但因爲須要等待全部訪問表的事務所有結束後才能成功,因此不算是"馬上"能完成的DDL。
e.g. ALTER TABLE `t1` ADD INDEX `idx1` (`name`(10) ASC) ;
建立二級索引除了修改表元信息以外,還須要在存儲引擎層創建相應的二級索引結構。
爲了支持併發的DML操做,MySQL還須要額外維護一份DDL期間的數據變動日誌,在DDL操做最後將併發的DML操做回放至新建的二級索引。不過因爲二級索引是經過聚簇索引構造,不須要包含全部的行數據,因此這還不能算是一種較高成本的操做。
e.g. ALTER TABLE `t1` DROP COLUMN `c1`;
刪除列和咱們以前提到的增長列狀況相似,因爲須要改動數據行,MySQL在InnoDB引擎內部須要重建聚簇索引 (按照聚簇索引生成臨時表, 再取而代之)。同時,爲了支持併發的DML操做,還須要維護DDL期間的數據變動日誌。可見當數據量較大時,這是一種很是高成本的操做。
e.g. ALTER TABLE `t1` MODIFY COLUMN `c1` INTEGER;
變動數據列類型,按照文檔描述這是一種沒法Inplace的操做,即須要MySQL在server層完成一次表的複製,相比由InnoDB內部完成重建,這種操做須要記錄Redo log,佔用更多的buffer pool。不過因爲在執行過程當中,沒法併發DML操做,不須要記錄DDL期間的變動日誌。即使如此,這仍然是一種高成本的操做。
DDL應顯式指定ALGORITHM,從低成本(INSTANT)到高成本(COPY)逐一嘗試,當不匹配時MySQL會報錯。以防咱們認爲的一個低成本的DDL,由於認爲失誤而須要重建表,形成運維事故。
在之前版本中,MySQL的DDL都須要重建表,因此會建議將一個表的多個變動寫在同一句DDL中,用一次重建實施多個變動。 而如今,若是一句DDL中的多個變動的算法不一樣,那麼會使用其中最高成本的算法。 運維中,須要仔細甄別狀況,使得一部分變動能夠更快完成上線。
DDL語句容許咱們選擇鎖類型和DDL類型,給予咱們更好的自由度。 好比當執行刪除列時,MySQL默認使用的是Inplace Rebuild操做,鎖級別是None (容許併發讀寫)。若是業務能夠妥協,那麼能夠將鎖級別設置爲SHARED (容許併發讀但阻塞寫),這樣DDL能夠更快完成。
本期咱們說添加列須要重建表,而MySQL引入的騰訊團隊的Instant方案 目標就是 讓添加列"馬上"完成。那麼Instant版本的添加列是如何完成的?
Instant 是否徹底不影響業務,是不是真正的"馬上"完成?
對於Inplace Rebuild,重建數據的過程與併發的DML如何不互相干擾?
本期思考題,咱們將在以後幾期圖解系列文章中逐一解析。