本文介紹如何使用MySQL 5.6及以上版本的新特性Online DDL。
RDS MySQL支持5.6及以上Online DDL特性。
Online DDL(在線DDL)功能允許在表上執行DDL的操作(例如創建索引)的同時不阻塞并發的DML操作和查詢(select)操作。
從低版本(例如RDS MySQL 5.5)升級到RDS MySQL 5.6時,第一次執行DDL時有可能會因為表數據的文件格式仍舊是5.5版本而不支持Online DDL特性。這種情況可以通過執行以下命令來轉換:
ALTER TABLE <表名> engine=innodb;
更多版本特性請參見AliSQL內核小版本發布記錄。
所有的DDL操作均建議在業務低峰期進行,以避免對業務產生影響。
Online DDL的限制
操作 | 是否支持Inplace方式 | 是否需要Copy Table | 是否允許并發DML | 是否允許并發查詢 | 備注 |
創建普通索引 | 支持 | 不需要 | 允許 | 允許 | 無。 |
創建全文索引 | 支持 | 不需要 | 不允許 | 允許 | 第一個全文索引需要通過Copy Table的方式創建;其后的全文索引可以通過Inplace方式創建。 |
刪除索引 | 支持 | 不需要 | 允許 | 允許 | 僅修改表元數據metadata。 |
優化表 | 支持 | 需要 | 允許 | 允許 | 如果表上創建有全文索引,則不支持algorithm=inplace選項。 |
設置列默認值 | 支持 | 不需要 | 允許 | 允許 | 僅修改表元數據metadata。 |
修改自增列值 | 支持 | 不需要 | 允許 | 允許 | 僅修改表元數據metadata。 |
添加外鍵約束 | 支持 | 不需要 | 允許 | 允許 |
|
刪除外鍵約束 | 支持 | 不需要 | 允許 | 允許 | foreign_key_checks選項開啟或者關閉都可以。 |
重命名列 | 支持 | 不需要 | 允許 | 允許 | 如果僅僅修改字段名稱,而不要修改字段類型,是支持并發DML操作的。 |
添加列 | 支持 | 需要 | 允許 | 允許 | 在添加auto_increment自增列時,是不允許并發 DML 操作的。 盡管支持Algorithm=INPLACE ,但因為數據實質上需要重新組織,因此操作的開銷高昂。 |
刪除列 | 支持 | 需要 | 允許 | 允許 | 盡管支持Algorithm=INPLACE ,但因為數據實質上需要重新組織,因此操作的開銷高昂。 |
修改各列順序 | 支持 | 需要 | 允許 | 允許 | 盡管支持Algorithm=INPLACE ,但因為數據實質上需要重新組織,因此操作的開銷高昂。 |
修改Row_Format屬性 | 支持 | 需要 | 允許 | 允許 | 盡管支持Algorithm=INPLACE ,但因為數據實質上需要重新組織,因此操作的開銷高昂。 |
修改Key_Block_Size屬性 | 支持 | 需要 | 允許 | 允許 | 盡管支持Algorithm=INPLACE ,但因為數據實質上需要重新組織,因此操作的開銷高昂。 |
設置列為空值Null | 支持 | 需要 | 允許 | 允許 | 盡管支持Algorithm=INPLACE ,但因為數據實質上需要重新組織,因此操作的開銷高昂。 |
設置列不為空值NOT Null | 支持 | 需要 | 允許 | 允許 | 該操作需要將SQL_MODE 參數設置為STRICT_ALL_TABLES或STRICT_TRANS_TABLES才能成功。如果列值中包含空值(NULL),則該DDL 操作會失敗。 盡管支持Algorithm=INPLACE ,但因為數據實質上需要重新組織,因此操作的開銷高昂。 |
修改列的數據類型 | 不支持 | 需要 | 不允許 | 允許 | 無。 |
添加主鍵 | 支持 | 需要 | 允許 | 允許 | 盡管支持Algorithm=INPLACE ,但因為數據實質上需要重新組織,因此操作的開銷高昂。 如果涉及的列需要轉換為NOT NULL,則不支持Algorithm=INPLACE。 |
刪除主鍵并添加新主鍵 | 支持 | 需要 | 允許 | 允許 | 僅當在同一個Alter Table語句中(刪除主鍵的DDL語句)添加新主鍵才支持Algorithm=INPLACE。 因為數據實質上需要重新組織,因此操作的開銷高昂。 |
刪除主鍵 | 不支持 | 需要 | 不允許 | 允許 | 無。 |
Convert character set | 不支持 | 需要 | 不允許 | 允許 | 如果新的字符集編碼不同,需要重建表。 |
Specify character set | 不支持 | 需要 | 不允許 | 允許 | 如果新的字符集編碼不同,需要重建表。 |
帶force選項重建表 | 支持 | 需要 | 允許 | 允許 | 如果表上有全文索引,則不支持Algorithm=Inplace選項。 |
重建表 alter table ... engine=innodb | 支持 | 需要 | 允許 | 允許 | 如果表上有全文索引,則不支持Algorithm=Inplace選項。 |
設置表的 persistent statistics | 支持 | 不需要 | 允許 | 允許 | 僅修改表的元數據metadata。 |
修改表注釋 | 支持 | 不需要 | 允許 | 允許 | 無。 |
是否支持Inplace方式:對應DDL語句的Algorithm選項,通過Inplace方式執行DDL。相比Copy Table的方式,可以減少空間和I/O消耗。
是否需要Copy Table:對應DDL語句的Algorithm選項,通過Copy Table的方式執行DDL。DDL執行期間會占用更大的磁盤空間和消耗更多的I/O。
是否允許并發DML:對應DDL語句的Lock選項,DDL執行期間是否支持并發DML操作。
是否允許并發查詢:DDL語句執行期間是否支持并發查詢操作(通常都是支持的)。
MySQL官方文檔請參見Online DDL 概覽。
DDL操作執行時需要修改表的元數據(metadata),有可能會遇到等待表元數據鎖的情況(waiting for table metadata lock),該情況的處理方式請參見解決MDL鎖導致無法操作數據庫的問題。
Inplace和Copy Table是相反的2種處理方式;但即使DDL支持Inplace選項,某些操作在整個執行過程中也會部分涉及到Copy Table,例如上表中的添加列操作。
Online DDL選項建議
Algorithm=Inplace :為了避免Copy Table導致的實例性能問題(空間、I/O問題),建議在DDL中包含該選項。如果DDL操作不支持Algorithm=Inplace方式,DDL操作會立刻返回錯誤。
ALTER TABLE area_bak algorithm=inplace, modify father text; ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.
Lock=None :為了在DDL操作過程中不影響業務DML 操作,建議在DDL中包含該選項。如果DDL操作不支持Lock=None (允許并行DML操作)選項,DDL操作會立刻返回錯誤。
alter table area ALGORITHM=copy, lock=none,CONVERT TO CHARACTER SET utf8mb4; ERROR 1846 (0A000): LOCK=NONE is not supported. Reason: COPY algorithm requires a lock. Try LOCK=SHARED.
默認情況下RDS MySQL會盡量使用algorithm=inplace以及lock=none來進行DDL操作,因此默認可以不指定這兩個選項。但如果擔心DDL操作對系統負載有影響或阻塞對目標表的DML操作,建議使用algorithm=inplace或lock=none選項來操作,這樣如果系統對某一個選項不支持,會立刻返回錯誤,避免影響業務。
示例
ALTER TABLE area algorithm=inplace, lock=none, add index idx_fa (father);
對不支持Online DDL的操作(例如RDS MySQL 5.5),可以考慮通過Percona的Schema Online Change工具來操作。
ALTER TABLE語法請參見ALTER TABLE Syntax。
異常處理
在對某些大表的Online DDL過程中,有時會碰到下面的錯誤:
ALTER TABLE rd_order_rec add index idx_cr_time_detail (cr_time,detail);
ERROR 1799(HY000): Creating index 'idx_cr_time_detail' required more than 'innodb_online_alter_log_max_size' bytes of modification log. Please try again.
原因
在進行Online DDL(不阻塞并發DML) 的過程中,每個被修改的表或者創建的索引都會使用一個臨時日志來保存 DDL過程中并發DML操作的記錄。該臨時日志文件的大小可以根據需要從參數innodb_sort_buffer_size指定的大小擴展到參數innodb_online_alter_log_max_size指定的大小。
如果有臨時日志文件大小超過上限,則該DDL語句返回失敗并且所有沒有提交的并發DML操作會被回滾。因此增加 innodb_online_alter_log_max_size參數的大小可以允許DDL過程中更多的并發DML操作,但是較大的值也會使在DDL操作末尾階段的鎖定表應用日志中的數據的過程持續更長的時間。
解決方法
針對MySQL 5.6及以上版本,可以在控制臺修改innodb_online_alter_log_max_size參數值,詳細步驟請參見設置實例參數。