MySQL的SQL語句 - 數據定義語句(6)- ALTER TABLE 語句(2)

性能和空間要求

使用以下算法之一處理ALTER TABLE操作:

● COPY:對原表的副本進行操作,將數據從原表中逐行復制到新表中。不允許併發DML。

● INPLACE:操作避免複製表數據,但可以就地重建表。在操作的準備和執行階段,可能會簡單地使用表上的獨佔元數據鎖。通常,支持併發DML。

● INSTANT:操作只修改數據字典中的元數據。在準備和執行期間,不會對錶執行排他元數據鎖,並且表數據不受影響,從而使操作立即生效。允許併發DML。(MySQL8.0.12引入)

ALGORITHM子句是可選的。如果省略了ALGORITHM子句,MySQL將爲存儲引擎和ALTER TABLE子句使用支持的ALGORITHM=INSTANT,否則,將使用ALGORITHM=INPLACE。如果不支持ALGORITHM=INPLACE,則使用ALGORITHM=COPY。

指定ALGORITHM子句要求操作對支持它的子句和存儲引擎使用指定的算法,否則將失敗並返回錯誤。指定ALGORITHM=DEFAULT與省略ALGORITHM子句相同。

使用COPY算法的ALTER TABLE操作等待正在修改表的其他操作完成。對錶副本應用更改後,將複製數據,刪除原始表,並將表副本重命名爲原始表的名稱。執行ALTER TABLE操作時,其他會話可以讀取原始表(很快會提到例外情況)。在 ALTER TABLE 操作開始後對錶的更新和寫入將被暫停,直到新表準備就緒,然後自動重定向到新表。表的臨時副本是在原始表的數據庫目錄中創建的,除非使用 RENAME TO 操作將表移動到另一個不同路徑的數據庫。

前面提到的例外情況是ALTER TABLE 阻塞準備從表和表定義緩存中清除過時的表結構時讀取(而不僅僅是寫入)。此時,它必須獲得獨佔鎖。爲此,它等待當前讀完成,並阻止新的讀寫操作。

使用COPY算法的ALTER TABLE操作可防止併發DML操作。仍然允許併發查詢。也就是說,表複製操作總是至少包含LOCK=SHARED的併發限制(允許查詢,但是不允許DML)。通過指定LOCK=EXCLUSIVE,可以進一步限制支持LOCK子句的併發操作,這將阻止DML和查詢。

要強制對ALTER TABLE操作使用COPY算法,否則將不使用它,請指定ALGORITHM=COPY或啓用old_alter_table系統變量。如果old_alter_table設置與值不是DEFAULT的ALGORITHM子句之間存在衝突,則ALGORITHM子句優先。

對於InnoDB表,針對駐留在共享表空間中的表使用COPY算法的ALTER TABLE操作可以增加表空間的使用量。這樣的操作需要與表中的數據加上索引一樣多的額外空間。對於駐留在共享表空間中的表,操作期間使用的額外空間不會像獨立表空間中的表那樣釋放回操作系統。

支持INPLACE算法的ALTER TABLE操作包括:

● InnoDB 聯機DDL特性支持的ALTER TABLE操作。

● 重命名錶。MySQL重命名與表tbl_name相對應的文件,而不進行復制。(也可以使用RENAME TABLE語句重命名錶。)專門爲重命名錶授予的權限不會遷移到新名稱。必須手動更改。

● 只修改表元數據的操作。這些操作是即時的,因爲服務器不接觸表內容。僅元數據操作包括:

■ 重命名列。在NDB Cluster 8.0.18及更高版本中,也可以聯機執行此操作。

■ 更改列的默認值(NDB表除外)。

■ 通過在有效成員值列表的末尾添加新的枚舉或集合成員來修改枚舉或集合列的定義,只要數據類型的存儲大小不變。例如,將一個成員添加到包含8個成員的SET列中,會將每個值所需的存儲空間從1個字節更改爲2個字節;這需要一個表副本。在列表中間添加成員會導致對現有成員重新編號,這需要表副本。

■ 更改空間列的定義來刪除SRID屬性。(添加或更改SRID屬性需要重新生成,並且無法就地完成,因爲服務器必須驗證所有值是否都具有指定的SRID值。)

■ 從MySQL8.0.14開始,在滿足以下條件時更改列字符集:

○ 列數據類型爲CHAR、VARCHAR、TEXT或ENUM。

○ 字符集的更改是從utf8mb3更改爲utf8mb4,或任何字符集更改爲二進制。

○ 列上沒有索引。

■ 從MySQL8.0.14開始,在滿足以下條件時更改生成的列:

○ 對於InnoDB表,修改生成的存儲列但不更改其類型、表達式或可爲空的語句。

○ 對於非InnoDB表,是指修改生成的存儲或虛擬列,但不更改其類型、表達式或可空的語句。

這種更改的一個例子是對列註釋的更改。

● 重命名索引。

● 爲InnoDB和NDB表添加或刪除輔助索引。

● 對於NDB表,在可變寬度列上添加和刪除索引的操作。這些操作是在線進行的,沒有表複製,也沒有在大多數持續時間內阻塞併發的DML操作。

● 使用ALTER INDEX操作修改索引可見性。

● 包含生成列的表的列修改,這些列依賴於具有默認值的列(如果已修改的列不包含在生成的列表達式中)。例如,可以在不重新生成表的情況下就地更改單獨列的NULL屬性。

支持INSTANT算法的ALTER TABLE操作包括:

● 添加列。此功能稱爲"即時添加列"。

● 添加或刪除虛擬列。

● 添加或刪除列默認值。

● 修改枚舉或集合列的定義。對於ALGORITHM=INSTANT,上面描述的限制也同樣適用。

● 更改索引類型。

● 重命名錶。對於ALGORITHM=INSTANT,上面描述的限制也同樣適用。

ALTER TABLE將MySQL 5.5臨時列升級爲5.6格式,用於ADD COLUMN、CHANGE COLUMN、MODIFY COLUMN、ADD INDEX和FORCE操作。不能使用INPLACE算法進行轉換,因爲表必須重建,在這種情況下指定ALGORITHM=INPLACE會引發錯誤,如有必要,指定ALGORITHM=COPY。

如果一個用於根據鍵對錶進行分區的多列索引上的ALTER TABLE操作更改了列的順序,則只能使用ALGORITHM=COPY執行。

WITHOUT VALIDATION和WITH VALIDATION子句影響ALTER TABLE是否對虛擬生成的列修改執行就地操作。

NDB Cluster 8.0支持使用與標準MySQL服務器相同的ALGORITHM=INPLACE語法進行聯機操作。NDB不支持聯機更改表空間;從NDB 8.0.21開始,不允許這樣做。

ALTER TABLE 聯合 DISCARD ... PARTITION ... TABLESPACE 或 IMPORT ... PARTITION ... TABLESPACE不創建任何臨時表或臨時分區文件。

ALTER TABLE 聯合 ADD PARTITION、DROP PARTITION、COALESCE PARTITION、REBUILD PARTITION 或 REORGANIZE PARTITION 不會創建臨時表(與NDB表一起使用時除外);但是,這些操作可以創建臨時分區文件。

RANGE或LIST分區的ADD或DROP操作是立即操作或幾乎是立即操作。除非使用LINEAR HASH 或 LINEAR KEY,否則HASH或KEY分區的ADD或者COALESCE操作會在所有分區之間複製數據;這實際上與創建新表相同,儘管ADD或COALESCE操作是按分區執行的。REORGANIZE操作只複製已更改的分區,不觸及未更改的分區。

對於MyISAM表,可以通過將 myisam_sort_buffer_size 系統變量設置爲較高的值來加快索引重新創建(轉換過程中最慢的部分)。

併發控制

對於支持它的ALTER TABLE操作,可以使用LOCK子句來控制在表被修改時併發讀和寫的級別。爲這個子句指定一個非默認值使您能夠在修改操作期間要求一定數量的併發訪問或排他性,並在請求的鎖定程度不可用時停止操作。

使用ALGORITHM=INSTANT的操作只允許LOCK = DEFAULT。其他LOCK子句參數不適用。

LOCK子句的參數是:

MySQL的SQL語句 - 數據定義語句(6)- ALTER TABLE 語句(2)

給定ALGORITHM子句(如果有)和ALTER TABLE操作的最大併發級別:如果支持,則允許併發讀和寫。如果不支持,則允許併發讀。如果不是,強制排他訪問。

MySQL的SQL語句 - 數據定義語句(6)- ALTER TABLE 語句(2)

如果支持,允許併發讀和寫。否則,將出現錯誤。

MySQL的SQL語句 - 數據定義語句(6)- ALTER TABLE 語句(2)

如果支持,允許併發讀,但阻塞寫。即使存儲引擎支持給定ALGORITHM子句(如果有的話)和ALTER TABLE操作的併發寫操作,也會阻塞寫操作。如果不支持併發讀取,則會發生錯誤。

MySQL的SQL語句 - 數據定義語句(6)- ALTER TABLE 語句(2)

執行獨佔訪問。即使存儲引擎對給定的ALGORITHM子句(如果有的話)和ALTER TABLE操作支持併發讀/寫,也會執行此操作。

官方文檔地址:
https://dev.mysql.com/doc/refman/8.0/en/alter-table.html

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