MySQL Online DDL

核心參考:https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html

Online DDL

OnlineDDL支持在線更改表結構的同時,運行DML語句。Online DDL是5.7版本的特性,主要包含:

  • 提高了業務的相應和可用性,不會造成業務的長時間不可用。
  • 在DDL操作使用鎖時,保證程序的併發和性能之前的平衡。
  • 比table-copy方式更少的IO和磁盤使用

通常,無需手動指定開啓OnlineDDL,MySQL會自行選擇。

同時,再alter語句中,我們也可以執行不使用任何鎖,語法如下:

ALTER TABLE tbl_name ADD PRIMARY KEY (column), ALGORITHM=INPLACE, LOCK=NONE;

索引操作

如下針對表索引操作的行爲支持Online DDL:

Operation In Place Rebuilds Table Permits Concurrent DML Only Modifies Metadata
Creating or adding a secondary index Yes No Yes No
Dropping an index Yes No Yes Yes
Renaming an index Yes No Yes Yes
Adding a FULLTEXT index Yes* No* No No
Adding a SPATIAL index Yes No No No
Changing the index type Yes No Yes Yes

語法和注意事項

創建和添加二級索引

CREATE INDEX name ON table (col_list);
ALTER TABLE tbl_name ADD INDEX name (col_list);

主鍵索引操作

需要注意的是,重建聚集索引總是需要拷貝表數據,所以我們在建一張表的時候最好指定主鍵。
如果創建一張表的時候,沒有指定主鍵,那麼InnoDB會選擇第一個UNIQUE NOT NULL 的列作爲主鍵,或者會系統自動生成一列。爲了避免不確定和隱藏列對空間的浪費,我們需要在創建表的時候指定主鍵列。
針對主鍵列的操作,即使我們使用ALGORITHM=INPLACE,實際操作仍然會使用複製算法ALGORITHM=COPY,但是實際的效率仍然大於ALGORITHM=COPY算法,原因如下:

  • ALGORITHM=INPLACE 不會產生undolog 和redo log
  • 二級索引是pre-sorted的,所以可以按順序加載
  • change buffer 沒有使用,因爲二級索引沒有隨機插入

其他操作

Online DDL的性能和併發性

Online DDL提高了MySQL的如下性能:

  • 提高應用程序的響應能力,因爲在進行DDL操作時,同時也可以進行DML操作。
  • In-place操作相比較表複製,減少了對磁盤IO以及CPU使用消耗。
  • In-place操作相對於表複製佔用更小的buffer pool

LOCK條件

默認MySQL在DDL操作時儘可能的少用鎖。LOCK條件可以限制MySQL使用鎖。如果一個DDL操作被LOCK條件限制了更低級別的鎖,那麼會直接報錯。LOCK的範圍由小到大如下排列:

  • LOCK=NONE: 允許併發查詢和DML語句
  • LOCK=SHARED: 允許併發查詢,但是禁止DML語句。
  • LOCK=DEFAULT: 儘可能的允許併發操作,比如併發查詢和DML語句
  • LOCK=EXCLUSIVE:阻塞併發查詢和DML語句

Online DDL and Metadata Locks

Online DDL可以看做有如下三個步驟:

  1. Initialization:初始化階段,服務器決定了當前操作允許的最大併發。同時,會對增加鎖 metadata lock 保護當前表的定義
  2. Execution:當前階段開始執行語句,metadata lock是否升級到排它鎖取決於1階段。一個排他metadata lock 只會在準備階段出現。
  3. Commit Table Definition:在提交表定義階段, metadata lock會升級爲排他鎖,然後刪除老的表定義,更新爲新的表定義。

Online DDl語句執行過程中,會持有metadata locks。
如下場景,演示一個Online DDL語句等到metadata locks:
session 1:

CREATE TABLE t1 (c1 INT) ENGINE=InnoDB;

START TRANSACTION;
SELECT * FROM t1;

如上事務,持有shared metadata lock。
session 2:

ALTER TABLE t1 ADD COLUMN x INT, ALGORITHM=INPLACE, LOCK=NONE;

如上Online DDL語句,需要exclusive metadata lock鎖在表t1,但是事務1並沒有釋放S meta lock,所以無法獲取鎖,會一直處於等待狀態。

session 3:

SELECT * FROM t1;

session 3也會被阻塞,因爲它會等待session 2的Alter語句持有exclusive metadata lock。
查看當前事務進程:

mysql> SHOW FULL PROCESSLIST;
+----+------+-----------+------+---------+------+---------------------------------+---------------------------------------------------------------+
| Id | User | Host      | db   | Command | Time | State                           | Info                                                          |
+----+------+-----------+------+---------+------+---------------------------------+---------------------------------------------------------------+
| 45 | root | localhost | test | Sleep   |  295 |                                 | NULL                                                          |
| 46 | root | localhost | test | Query   |  249 | Waiting for table metadata lock | ALTER TABLE t1 ADD COLUMN x INT, ALGORITHM=INPLACE, LOCK=NONE |
| 47 | root | localhost | test | Query   |  149 | Waiting for table metadata lock | SELECT * FROM t1                                              |
| 48 | root | localhost | test | Query   |    0 | init                            | SHOW FULL PROCESSLIST                                         |
+----+------+-----------+------+---------+------+---------------------------------+---------------------------------------------------------------+

這裏也向我們展示了,爲什麼現在的Online DDL仍然會出現死鎖。所以儘量不要在事務高峯期執行DDL SQL語句。

Online DDL 性能

OnlineDDL的性能取決於當前操作是替換還是重建操作。
如下我們可以測試下,DDL的性能:
本地自建一張表,表數據量3500萬行左右,通過設置ALGORITHM=INPLACE和ALGORITHM=COPY來測試增加索引的性能:

ALTER TABLE student ADD INDEX idx_name(name) USING BTREE, ALGORITHM=INPLACE;

如上sql Query OK, 0 rows affected (81.06 sec)

ALTER TABLE student ADD INDEX idx_name(name) USING BTREE, ALGORITHM=COPY;

如上sql Query OK, 35583932 rows affected (1260.93 sec)

所以建議在給一張大表運行DDL語句時,我們最好對大表做一張複製表,然後針對複製表操作,看下耗時和影響行數,行數爲0 則沒有發生表複製。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章