中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MySQL5.6在線表結構變更(online ddl)總結

發布時間:2020-07-15 12:03:34 來源:網絡 閱讀:3954 作者:yzy121403725 欄目:MySQL數據庫

  MySQL從5.6.17以后,支持在線修改表結構操作(online ddl),即在變更表結構的過程中,不阻塞dml和dql操作.

  根據操作過程中是否需要表拷貝,online ddl可分為下面兩大類:

1.需要表拷貝的 ddl 操作:
增加、刪除、重排列。
增加、刪除主鍵。
改變表的 ROW_FORMAT 或 KEY_BLOCK_SIZE屬性。
改變的字段的null狀態。
執行OPTIMIZE TABLE,優化表。
使用 FORCE 選項重建表。
使用ALTER TABLE ... ENGINE=INNODB 語句。
首次創建全文索引。


2.不需要表拷貝的 ddl 操作:
創建、增加、刪除普通索引。
創建第二個及后續的全文索引。
為字段設置默認值。
改變auto-increment值。
刪除外鍵約束。
添加外鍵約束( 只有在foreign_key_checks=off時)
僅僅改變列的名稱
設置表的持續統計選項(STATS_PERSISTENT, STATS_AUTO_RECALC STATS_SAMPLE_PAGES)

特別說明:全文索引需要特別注意,創建了全文索引的表基本上不支持在線ddl操作。

ySQL 5.6 Online DDL把這種特性擴展到了添加列、刪除列、修改列類型、列重命名、設置默認值等等,實際效果要看所使用的選項和操作類別來定。

1.1 Online DDL選項

MySQL 在線DDL分為 INPLACE 和 COPY 兩種方式,通過在ALTER語句的ALGORITHM參數指定。

  • ALGORITHM=INPLACE,可以避免重建表帶來的IO和CPU消耗,保證ddl期間依然有良好的性能和并發。

  • ALGORITHM=COPY,需要拷貝原始表,所以不允許并發DML寫操作,可讀。這種copy方式的效率還是不如 inplace ,因為前者需要記錄undo和redo log,而且因為臨時占用buffer pool引起短時間內性能受影響。

上面只是 Online DDL 內部的實現方式,此外還有 LOCK 選項控制是否鎖表,根據不同的DDL操作類型有不同的表現:默認mysql盡可能不去鎖表,但是像修改主鍵這樣的昂貴操作不得不選擇鎖表。

  • LOCK=NONE,即DDL期間允許并發讀寫涉及的表,比如為了保證 ALTER TABLE 時不影響用戶注冊或支付,可以明確指定,好處是如果不幸該 alter語句不支持對該表的繼續寫入,則會提示失敗,而不會直接發到庫上執行。ALGORITHM=COPY默認LOCK級別

  • LOCK=SHARED,即DDL期間表上的寫操作會被阻塞,但不影響讀取。

  • LOCK=DEFAULT,讓mysql自己去判斷lock的模式,原則是mysql盡可能不去鎖表

  • LOCK=EXCLUSIVE,即DDL期間該表不可用,堵塞任何讀寫請求。如果你想alter操作在最短的時間內完成,或者表短時間內不可用能接受,可以手動指定。

但是有一點需要說明,無論任何模式下,online ddl開始之前都需要一個短時間排它鎖(exclusive)來準備環境,所以alter命令發出后,會首先等待該表上的其它操作完成,在alter命令之后的請求會出現等待waiting meta data lock。同樣在ddl結束之前,也要等待alter期間所有的事務完成,也會堵塞一小段時間。所以盡量在ALTER TABLE之前確保沒有大事務在執行,否則一樣出現連環鎖表。

1.2 考慮不同的DDL操作類別

從上面的介紹可以看出,不是5.6支持在線ddl就可以隨心所欲的alter table,鎖不鎖表要看情況:

提示:下表根據官方 Summary of Online Status for DDL Operations 整理挑選的常用操作。

  • In-Place為Yes是優選項,說明該操作支持INPLACE

  • Copies Table為No是優選項,因為為Yes需要重建表。大部分情況與In-Place是相反的

  • Allows Concurrent DML?為Yes是優選項,說明ddl期間表依然可讀寫,可以指定 LOCK=NONE(如果操作允許的話mysql自動就是NONE)

  • Allows Concurrent Query?默認所有DDL操作期間都允許查詢請求,放在這只是便于參考

  • Notes會對前面幾列Yes/No帶*號的限制說明

OperationIn-Place?Copies Table?Allows Concurrent DML?Allows Concurrent Query?Notes
添加索引Yes*No*YesYes對全文索引的一些限制
刪除索引YesNoYesYes僅修改表的元數據
OPTIMIZE TABLEYesYesYesYes從 5.6.17開始使用ALGORITHM=INPLACE,當然如果指定了old_alter_table=1或mysqld啟動帶--skip-new則將還是COPY模式。如果表上有全文索引只支持COPY
對一列設置默認值YesNoYesYes僅修改表的元數據
對一列修改auto-increment 的值YesNoYesYes僅修改表的元數據
添加 foreign key constraintYes*No*YesYes為了避免拷貝表,在約束創建時會禁用foreign_key_checks
刪除 foreign key constraintYesNoYesYesforeign_key_checks 不影響
改變列名Yes*No*Yes*Yes為了允許DML并發, 如果保持相同數據類型,僅改變列名
添加列Yes*Yes*Yes*Yes盡管允許 ALGORITHM=INPLACE ,但數據大幅重組,所以它仍然是一項昂貴的操作。當添加列是auto-increment,不允許DML并發
刪除列YesYes*YesYes盡管允許 ALGORITHM=INPLACE ,但數據大幅重組,所以它仍然是一項昂貴的操作
修改列數據類型NoYes*NoYes修改類型或添加長度,都會拷貝表,而且不允許更新操作
更改列順序YesYesYesYes盡管允許 ALGORITHM=INPLACE ,但數據大幅重組,所以它仍然是一項昂貴的操作
修改ROW_FORMAT
和KEY_BLOCK_SIZE
YesYesYesYes盡管允許 ALGORITHM=INPLACE ,但數據大幅重組,所以它仍然是一項昂貴的操作
設置列屬性NULL
或NOT NULL
YesYesYesYes盡管允許 ALGORITHM=INPLACE ,但數據大幅重組,所以它仍然是一項昂貴的操作
添加主鍵Yes*YesYesYes盡管允許 ALGORITHM=INPLACE ,但數據大幅重組,所以它仍然是一項昂貴的操作。
如果列定義必須轉化NOT NULL,則不允許INPLACE
刪除并添加主鍵YesYesYesYes在同一個 ALTER TABLE 語句刪除就主鍵、添加新主鍵時,才允許inplace;數據大幅重組,所以它仍然是一項昂貴的操作。
刪除主鍵NoYesNoYes不允許并發DML,要拷貝表,而且如果沒有在同一 ATLER TABLE 語句里同時添加主鍵則會收到限制
變更表字符集NoYesNoYes如果新的字符集編碼不同,重建表

從表看出,In-Place為No,DML一定是No,說明ALGORITHM=COPY一定會發生拷貝表,只讀。但ALGORITHM=INPLACEE也要可能發生拷貝表,但可以并發DML:

  • 添加、刪除列,改變列順序

  • 添加或刪除主鍵

  • 改變行格式ROW_FORMAT和壓縮塊大小KEY_BLOCK_SIZE

  • 改變列NULL或NOT NULL

  • 優化表OPTIMIZE TABLE

  • 強制 rebuild 該表

不允許并發DML的情況有:修改列數據類型、刪除主鍵、變更表字符集,即這些類型操作ddl是不能online的。

另外,更改主鍵索引與普通索引處理方式是不一樣的,主鍵即聚集索引,體現了表數據在物理磁盤上的排列,包含了數據行本身,需要拷貝表;而普通索引通過包含主鍵列來定位數據,所以普通索引的創建只需要一次掃描主鍵即可,而且是在已有數據的表上建立二級索引,更緊湊,將來查詢效率更高。

修改主鍵也就意味著要重建所有的普通索引。刪除二級索引更簡單,修改InnoDB系統表信息和數據字典,標記該所以不存在,標記所占用的表空間可以被新索引或數據行重新利用。


MySQL5.6幾種建索引方式比較。
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.6.17 |
+-----------+
mysql> CREATE TABLE test AS SELECT * FROM information_schema.columns;
mysql> INSERT INTO test SELECT * FROM test;
mysql> INSERT INTO test SELECT * FROM test;
mysql> SELECT COUNT(1) FROM test;
+----------+
| COUNT(1) |
+----------+
| 312928 |
+----------+
1 row in set (0.17 sec)

ALGORITHM=inplace,就地進行,如果允許的話則修改操作可以直接在該表上執行。

mysql> CREATE INDEX ind_t_column_name ON test(column_name) ALGORITHM=inplace;
Query OK, 0 rows affected (1.54 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> ALTER TABLE test DROP INDEX ind_t_column_name;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0


mysql> CREATE INDEX ind_t_column_name ON test(column_name);
Query OK, 0 rows affected (1.70 sec)
Records: 0 Duplicates: 0 Warnings: 0

ALGORITHM=copy,用于標識改操作是否需要整個表。
mysql> CREATE INDEX ind_t_column_name ON test(column_name) ALGORITHM=copy;
Query OK, 312928 rows affected (5.93 sec)

Records: 312928 Duplicates: 0 Warnings: 0

注:

SET old_alter_table=0; --ALGORITHM=inplace

SET old_alter_table=1; --ALGORITHM=copy


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沙坪坝区| 成武县| 涟源市| 错那县| 隆安县| 阳东县| 利津县| 永和县| 浮山县| 平安县| 含山县| 太保市| 新干县| 弥渡县| 当涂县| 拉孜县| 河北区| 望江县| 甘孜县| 密云县| 新余市| 沂源县| 涟源市| 溆浦县| 南川市| 天门市| 乐安县| 成武县| 临颍县| 大邑县| 栖霞市| 扎鲁特旗| 灌云县| 龙岩市| 临朐县| 庄浪县| 玛纳斯县| 科尔| 清丰县| 灵武市| 泽库县|