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操作,开发者和数据库管理员能够在保证数据库可用性的前提下,灵活、高效地对数据库结构进行调整,满足业务发展的需求。