MySQL的在线数据定义语言(DDL)操作允许在对数据库对象进行结构修改时,最大限度减少对数据库可用性的影响,保证业务的连续性。本文将深入分析MySQL中各类在线DDL操作的支持情况、语法示例以及使用注意事项。
一、索引操作
(一)支持情况概述
MySQL对多种索引操作提供了在线支持,具体信息如下:
| 操作 | 原地操作 | 重建表 | 允许并发DML | 仅修改元数据 |
|---|
| 创建或添加二级索引 | 是 | 否 | 是 | 否 |
| 删除索引 | 是 | 否 | 是 | 是 |
| 重命名索引 | 是 | 否 | 是 | 是 |
| 添加FULLTEXT索引 | 是* | 否* | 否 | 否 |
| 添加SPATIAL索引 | 是 | 否 | 否 | 否 |
| 更改索引类型 | 是 | 否 | 是 | 是 |
(二)语法与使用说明
- 创建或添加二级索引:可以使用
CREATE INDEX或ALTER TABLE ADD INDEX语句。在创建索引期间,表仍可进行读写操作,并且索引创建完成时会反映表的最新内容。若服务器在创建过程中退出,恢复时会删除部分创建的索引,需重新执行创建语句。 - 删除索引:使用
DROP INDEX或ALTER TABLE DROP INDEX语句,删除索引时表可继续进行读写操作。 - 重命名索引:使用
ALTER TABLE... RENAME INDEX语句,并指定ALGORITHM=INPLACE和LOCK=NONE。 - 添加FULLTEXT索引:首次添加FULLTEXT索引且表中没有用户定义的
FTS_DOC_ID列时会重建表,后续添加通常无需重建表。 - 添加SPATIAL索引:使用
CREATE TABLE或ALTER TABLE ADD SPATIAL INDEX语句,并指定ALGORITHM=INPLACE和LOCK=SHARED。 - 更改索引类型:使用
ALTER TABLE语句,先删除原索引,再添加新类型的索引,并指定ALGORITHM=INPLACE。
二、主键操作
(一)支持情况概述
| 操作 | 原地操作 | 重建表 | 允许并发DML | 仅修改元数据 |
|---|
| 添加主键 | 是 | 是 | 是 | 否 |
| 删除主键 | 否 | 是 | 否 | 否 |
| 删除主键并添加另一个 | 是 | 是 | 是 | 否 |
(二)语法与使用说明
- 添加主键:使用
ALTER TABLE ADD PRIMARY KEY语句,并指定ALGORITHM=INPLACE和LOCK=NONE。但在某些情况下,如列需要转换为NOT NULL时,可能不允许使用ALGORITHM=INPLACE。添加主键时,MySQL会检查列中是否存在重复值和NULL值。 - 删除主键:使用
ALTER TABLE DROP PRIMARY KEY语句,并指定ALGORITHM=COPY。 - 删除主键并添加另一个:使用
ALTER TABLE DROP PRIMARY KEY, ADD PRIMARY KEY语句,并指定ALGORITHM=INPLACE和LOCK=NONE。此操作会大幅重组数据,较为昂贵。
三、列操作
(一)支持情况概述
| 操作 | 原地操作 | 重建表 | 允许并发DML | 仅修改元数据 |
|---|
| 添加列 | 是 | 是 | 是* | 否 |
| 删除列 | 是 | 是 | 是 | 否 |
| 重命名列 | 是 | 否 | 是* | 是 |
| 重新排序列 | 是 | 是 | 是 | 否 |
| 设置列默认值 | 是 | 否 | 是 | 是 |
| 更改列数据类型 | 否 | 是 | 否 | 否 |
| 扩展VARCHAR列大小 | 是 | 否 | 是 | 是 |
| 删除列默认值 | 是 | 否 | 是 | 是 |
| 更改自增数值 | 是 | 否 | 是 | 否* |
| 使列可为NULL | 是 | 是* | 是 | 否 |
| 使列不可为NULL | 是* | 是* | 是 | 否 |
| 修改ENUM或SET列定义 | 是 | 否 | 是 | 是 |
(二)语法与使用说明
- 添加列:使用
ALTER TABLE ADD COLUMN语句,并指定ALGORITHM=INPLACE和LOCK=NONE。添加自增列时不允许并发DML。 - 删除列:使用
ALTER TABLE DROP COLUMN语句,并指定ALGORITHM=INPLACE和LOCK=NONE。 - 重命名列:使用
ALTER TABLE CHANGE语句,并指定ALGORITHM=INPLACE和LOCK=NONE。保持数据类型和[NOT] NULL属性不变时,可支持并发DML。 - 重新排序列:使用
CHANGE或MODIFY操作中的FIRST或AFTER关键字,并指定ALGORITHM=INPLACE和LOCK=NONE。 - 更改列数据类型:使用
ALTER TABLE CHANGE语句,并指定ALGORITHM=COPY。 - 扩展VARCHAR列大小:使用
ALTER TABLE CHANGE COLUMN语句,并指定ALGORITHM=INPLACE和LOCK=NONE。但需注意长度字节的限制。 - 设置列默认值:使用
ALTER TABLE ALTER COLUMN SET DEFAULT语句,并指定ALGORITHM=INPLACE和LOCK=NONE。 - 删除列默认值:使用
ALTER TABLE ALTER COLUMN DROP DEFAULT语句,并指定ALGORITHM=INPLACE和LOCK=NONE。 - 更改自增数值:使用
ALTER TABLE AUTO_INCREMENT=next_value语句,并指定ALGORITHM=INPLACE和LOCK=NONE。 - 使列可为NULL:使用
ALTER TABLE MODIFY COLUMN语句,并指定ALGORITHM=INPLACE和LOCK=NONE。 - 使列不可为NULL:使用
ALTER TABLE MODIFY COLUMN语句,并指定ALGORITHM=INPLACE和LOCK=NONE。需启用STRICT_ALL_TABLES或STRICT_TRANS_TABLES SQL模式,且列中不能包含NULL值。 - 修改ENUM或SET列定义:使用
ALTER TABLE MODIFY COLUMN语句,并指定ALGORITHM=INPLACE和LOCK=NONE。在不改变存储大小的情况下,可添加新成员。
四、生成列操作
(一)支持情况概述
| 操作 | 原地操作 | 重建表 | 允许并发DML | 仅修改元数据 |
|---|
| 添加STORED列 | 否 | 是 | 否 | 否 |
| 修改STORED列顺序 | 否 | 是 | 否 | 否 |
| 删除STORED列 | 是 | 是 | 是 | 否 |
| 添加VIRTUAL列 | 是 | 否 | 是 | 是 |
| 修改VIRTUAL列顺序 | 否 | 是 | 否 | 否 |
| 删除VIRTUAL列 | 是 | 否 | 是 | 是 |
(二)语法与使用说明
- 添加STORED列:使用
ALTER TABLE ADD COLUMN语句,并指定ALGORITHM=COPY。因为服务器需要评估表达式,所以不是原地操作。 - 修改STORED列顺序:使用
ALTER TABLE MODIFY COLUMN语句,并指定ALGORITHM=COPY。 - 删除STORED列:使用
ALTER TABLE DROP COLUMN语句,并指定ALGORITHM=INPLACE和LOCK=NONE。 - 添加VIRTUAL列:对于非分区表,使用
ALTER TABLE ADD COLUMN语句,并指定ALGORITHM=INPLACE和LOCK=NONE。但不能与其他ALTER TABLE操作组合。对于分区表,不是原地操作。 - 修改VIRTUAL列顺序:使用
ALTER TABLE MODIFY COLUMN语句,并指定ALGORITHM=COPY。 - 删除VIRTUAL列:对于非分区表,使用
ALTER TABLE DROP COLUMN语句,并指定ALGORITHM=INPLACE和LOCK=NONE。但不能与其他ALTER TABLE操作组合。对于分区表,不是原地操作。
五、外键操作
(一)支持情况概述
| 操作 | 原地操作 | 重建表 | 允许并发DML | 仅修改元数据 |
|---|
| 添加外键约束 | 是* | 否 | 是 | 是 |
| 删除外键约束 | 是 | 否 | 是 | 是 |
(二)语法与使用说明
- 添加外键约束:当
foreign_key_checks禁用时,支持INPLACE算法,否则仅支持COPY算法。使用ALTER TABLE ADD CONSTRAINT语句。 - 删除外键约束:使用
ALTER TABLE DROP FOREIGN KEY语句。也可在同一语句中删除外键及其关联索引。可通过SHOW CREATE TABLE或查询Information Schema TABLE_CONSTRAINTS表获取外键约束名称。
六、表操作
(一)支持情况概述
| 操作 | 原地操作 | 重建表 | 允许并发DML | 仅修改元数据 |
|---|
| 更改ROW_FORMAT | 是 | 是 | 是 | 否 |
| 更改KEY_BLOCK_SIZE | 是 | 是 | 是 | 否 |
| 设置持久表统计信息 | 是 | 否 | 是 | 是 |
| 指定字符集 | 是 | 是 | 是 | 否 |
| 转换字符集 | 否 | 是 | 否 | 否 |
| 优化表 | 是 | 是 | 是 | 否 |
| 使用FORCE选项重建表 | 是 | 是 | 是 | 否 |
| 执行空重建 | 是 | 是 | 是 | 否 |
| 重命名表 | 是 | 否 | 是 | 是 |
(二)语法与使用说明
- 更改ROW_FORMAT:使用
ALTER TABLE ROW_FORMAT = row_format语句,并指定ALGORITHM=INPLACE和LOCK=NONE。此操作会大幅重组数据。 - 更改KEY_BLOCK_SIZE:使用
ALTER TABLE KEY_BLOCK_SIZE = value语句,并指定ALGORITHM=INPLACE和LOCK=NONE。此操作会大幅重组数据。 - 设置持久表统计信息选项:使用
ALTER TABLE STATS_PERSISTENT=0, STATS_SAMPLE_PAGES=20, STATS_AUTO_RECALC=1语句,并指定ALGORITHM=INPLACE和LOCK=NONE。此操作仅修改表元数据。 - 指定字符集:使用
ALTER TABLE CHARACTER SET = charset_name语句,并指定ALGORITHM=INPLACE和LOCK=NONE。若新字符编码不同,会重建表。 - 转换字符集:使用
ALTER TABLE CONVERT TO CHARACTER SET charset_name语句,并指定ALGORITHM=COPY。若新字符编码不同,会重建表。 - 优化表:使用
OPTIMIZE TABLE语句。对于包含FULLTEXT索引的表,不支持原地操作,且不允许使用ALGORITHM和LOCK语法。 - 使用FORCE选项重建表:使用
ALTER TABLE FORCE语句,并指定ALGORITHM=INPLACE和LOCK=NONE。自MySQL 5.6.17起支持ALGORITHM=INPLACE,但对于包含FULLTEXT索引的表不支持。 - 执行空重建:使用
ALTER TABLE ENGINE=InnoDB语句,并指定ALGORITHM=INPLACE和LOCK=NONE。自MySQL 5.6.17起支持ALGORITHM=INPLACE,但对于包含FULLTEXT索引的表不支持。 - 重命名表:使用
ALTER TABLE RENAME TO语句,并指定ALGORITHM=INPLACE和LOCK=NONE。也可使用RENAME TABLE语句。重命名表时,需手动更改授予原表的特权。
七、表空间操作
(一)支持情况概述
| 操作 | 原地操作 | 重建表 | 允许并发DML | 仅修改元数据 |
|---|
| 启用或禁用文件表空间加密 | 否 | 是 | 否 | 否 |
(二)语法与使用说明
使用ALTER TABLE ENCRYPTION='Y'语句,并指定ALGORITHM=COPY。加密仅支持文件表空间。
八、分区操作
(一)支持情况概述
多数ALTER TABLE分区子句不通过与常规非分区InnoDB表相同的内部在线DDL API,因此其在线支持情况有所不同。以下是部分分区操作的在线状态:
| 分区子句 | 原地操作 | 允许DML | 备注 |
|---|
| PARTITION BY | 否 | 否 | 允许ALGORITHM=COPY,`LOCK={DEFAULT |
| ADD PARTITION | 否 | 否 | 仅允许ALGORITHM=DEFAULT,LOCK=DEFAULT。对于按RANGE或LIST分区的表,不复制现有数据。对于按HASH或LIST分区的表,允许并发查询,MySQL在复制数据时持有共享锁 |
| DROP PARTITION | 否 | 否 | 仅允许ALGORITHM=DEFAULT,LOCK=DEFAULT。对于按RANGE或LIST分区的表,不复制现有数据 |
| DISCARD PARTITION | 否 | 否 | 仅允许ALGORITHM=DEFAULT,LOCK=DEFAULT |
| IMPORT PARTITION | 否 | 否 | 仅允许ALGORITHM=DEFAULT,LOCK=DEFAULT |
| TRUNCATE PARTITION | 是 | 是 | 不复制现有数据,仅删除行,不改变表或其分区的定义 |
| COALESCE PARTITION | 否 | 否 | 仅允许ALGORITHM=DEFAULT,LOCK=DEFAULT。对于按HASH或LIST分区的表,允许并发查询,MySQL在复制数据时持有共享锁 |
| REORGANIZE PARTITION | 否 | 否 | 仅允许ALGORITHM=DEFAULT,LOCK=DEFAULT。对于按LINEAR HASH或LIST分区的表,允许并发查询,MySQL在复制受影响分区的数据时持有共享元数据锁 |
| EXCHANGE PARTITION | 是 | 是 | |
| ANALYZE PARTITION | 是 | 是 | |
| CHECK PARTITION | 是 | 是 | |
| OPTIMIZE PARTITION | 否 | 否 | ALGORITHM和LOCK子句被忽略,重建整个表 |
| REBUILD PARTITION | 否 | 否 | 仅允许ALGORITHM=DEFAULT,LOCK=DEFAULT。对于按LINEAR HASH或LIST分区的表,允许并发查询,MySQL在复制受影响分区的数据时持有共享元数据锁 |
| REPAIR PARTITION | 是 | 是 | |
| REMOVE PARTITIONING | 否 | 否 | 允许ALGORITHM=COPY,`LOCK={DEFAULT |
(二)语法与使用说明
非分区在线ALTER TABLE操作对分区表遵循与常规表相同的规则,但会对每个表分区执行在线操作,可能增加系统资源需求。如需了解更多关于ALTER TABLE分区子句的信息,可参考相关文档。
通过深入了解MySQL的在线DDL操作,开发者和数据库管理员能够在保证数据库可用性的前提下,灵活、高效地对数据库结构进行调整,满足业务发展的需求。