首页 > 数据库 > > 14.13 InnoDB 在线 DDL
参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl.html
在线DDL功能允许就地表更改或并发DML,或两者兼而有之。 此功能的好处包括:
通常,您无需执行任何特殊操作即可启用在线DDL。 默认情况下,MySQL在允许的情况下执行操作,并尽可能少地锁定。
您可以使用ALTER TABLE语句的LOCK和ALGORITHM子句控制DDL操作的各个方面。 这些子句放在语句的末尾,用逗号分隔表和列。 例如:
ALTER TABLE tbl_name ADD PRIMARY KEY (column), ALGORITHM=INPLACE, LOCK=NONE;
LOCK子句可用于微调对表的并发访问程度。 ALGORITHM子句主要用于性能比较,并且在遇到任何问题时作为旧表复制行为的后备。 例如:
14.13.1 在线 DDL 操作
索引操作
创建或增加二级索引,删除索引,重命名索引都支持in-place的方式,均支持并发DML,但是不能重建表。其中,删除索引和重命名索引只修改元数据。
语法和使用注意:
CREATE INDEX name ON table (col_list);
ALTER TABLE tbl_name ADD INDEX name (col_list);
在创建索引时,该表仍可用于读写操作。 CREATE INDEX语句仅在完成访问表的所有事务完成后才结束,因此索引的初始状态反映了表的最新内容。
在线DDL支持添加二级索引意味着您通常可以通过先创建没有二级索引的表,再加载数据,最后添加二级索引,来加速创建和加载表及相关索引的整个过程。
新创建的辅助索引仅包含CREATE INDEX或ALTER TABLE语句完成执行时表中的已提交数据。 它不包含任何未提交的值,旧版本的值或标记为删除但尚未从旧索引中删除的值。
如果服务器在创建二级索引时退出,则在恢复时,MySQL会删除任何部分创建的索引。 您必须重新运行ALTER TABLE或CREATE INDEX语句。
某些因素会影响此操作的性能,空间使用和语义。
ALTER TABLE tbl_name RENAME INDEX old_index_name TO new_index_name, ALGORITHM=INPLACE, LOCK=NONE;
CREATE FULLTEXT INDEX name ON table(column);
如果没有用户定义的FTS_DOC_ID列,则添加第一个FULLTEXT索引会重建表。 可以添加其他FULLTEXT索引而无需重建表。
CREATE TABLE geom (g GEOMETRY NOT NULL);
ALTER TABLE geom ADD SPATIAL INDEX(g), ALGORITHM=INPLACE, LOCK=SHARED;
如果没有用户定义的FTS_DOC_ID列,则添加第一个FULLTEXT索引会重建表。 可以添加其他FULLTEXT索引而无需重建表。
主键操作
增加和删除并增加 主键都支持in-place,重建表,可并发DML,并不仅仅只修改元数据。
删除主键 不支持并发DML和in-place,并不仅仅只修改元数据。
语法和使用说明
ALTER TABLE tbl_name ADD PRIMARY KEY (column), ALGORITHM=INPLACE, LOCK=NONE;
在in-place的方式重建表。 数据进行了大量重组,使其成为一项昂贵的操作。 如果必须将列转换为NOT NULL,则在某些条件下不允许ALGORITHM = INPLACE。
重构聚簇索引总是需要复制表数据。 因此,最好在创建表时定义主键,而不是稍后发出ALTER TABLE ... ADD PRIMARY KEY。
当您创建UNIQUE或PRIMARY KEY索引时,MySQL必须做一些额外的工作。 对于UNIQUE索引,MySQL检查该表是否包含key的重复值。 对于PRIMARY KEY索引,MySQL还会检查PRIMARY KEY列中是否包含NULL。
当您使用ALGORITHM = COPY子句添加主键时,MySQL会将关联列中的NULL值转换为默认值:number为0,基于字符的列和BLOB为空字符串,DATETIME为 0000-00-00 00:00:00 。 这是Oracle建议您不要依赖的非标准行为。 仅当SQL_MODE设置包含strict_trans_tables或strict_all_tables标志时,才允许使用ALGORITHM = INPLACE添加主键。 当SQL_MODE设置为strict时,允许ALGORITHM = INPLACE,但如果请求的主键列包含NULL值,则语句仍然可能失败。 ALGORITHM = INPLACE行为更符合标准。
如果你创建一个没有主键的表,InnoDB会为你选择一个,它可以是在NOT NULL列上定义的第一个UNIQUE键,或者是系统生成的键。 为避免不确定性以及额外隐藏列的潜在空间要求,请将PRIMARY KEY子句指定为CREATE TABLE语句的一部分。
MySQL通过将原始表中的现有数据复制到具有所需索引结构的临时表来创建新的聚簇索引。 将数据完全复制到临时表后,原始表被不同的临时表重命名。这样临时表就包含原表被重命名的新聚簇索引,并从数据库中删除原始表。
适用于二级索引上的操作的online 性能增强不适用于主键索引。 InnoDB表的行存储在基于主键组织的聚簇索引中,形成一些数据库系统称为“索引组织表”的内容。 由于表结构与主键紧密相关,因此重新定义主键仍需要复制数据。
当主键上的操作使用ALGORITHM = INPLACE时,即使仍然复制数据,它也比使用ALGORITHM = COPY更有效,因为:
如果服务器在创建新的聚簇索引时退出,则不会丢失任何数据,但必须使用进程中存在的临时表完成恢复过程。 由于很少在大型表上重新创建聚簇索引或重新定义主键,或者在此操作期间遇到系统崩溃,因此本手册不提供有关从此方案中恢复的信息。
ALTER TABLE tbl_name DROP PRIMARY KEY, ALGORITHM=COPY;
只有ALGORITHM = COPY支持删除主键而不在同一个ALTER TABLE语句中添加新主键。
ALTER TABLE tbl_name DROP PRIMARY KEY, ADD PRIMARY KEY (column), ALGORITHM=INPLACE, LOCK=NONE;
数据进行了大量重组,使其成为一项昂贵的操作。
字段操作
除了改变字段类型以外的字段操作,均支持并发DML。所有的操作都支持in-place的方式。
语法和使用说明
ALTER TABLE tbl_name ADD COLUMN column_name column_definition, ALGORITHM=INPLACE, LOCK=NONE;
添加自动增量列时不允许并发DML。 数据进行了大量重组,使其成为一项昂贵的操作。
ALTER TABLE tbl_name DROP COLUMN column_name, ALGORITHM=INPLACE, LOCK=NONE;
数据进行了大量重组,使其成为一项昂贵的操作。
ALTER TABLE tbl CHANGE old_col_name new_col_name data_type, ALGORITHM=INPLACE, LOCK=NONE;
要允许并发DML,请保留相同的数据类型并仅更改列名称。
当您保持相同的数据类型和[NOT] NULL属性时,只更改列名,操作始终可以在线执行。
您还可以重命名属于外键约束的列。 外键定义会自动更新以使用新列名称。 重命名参与外键的列仅适用于ALGORITHM = INPLACE。 如果使用ALGORITHM = COPY子句,或某些其他条件导致命令在后台使用ALGORITHM = COPY,则ALTER TABLE语句将失败。
生成列不支持ALGORITHM = INPLACE重命名。
要重新排序字段,在change 或modify 操作中 使用 first 或 after。
ALTER TABLE tbl_name MODIFY COLUMN col_name column_definition FIRST, ALGORITHM=INPLACE, LOCK=NONE;
数据进行了大量重组,使其成为一项昂贵的操作。
ALTER TABLE tbl_name CHANGE c1 c1 BIGINT, ALGORITHM=COPY;
更改列数据类型 只支持 ALGORITHM=COPY
ALTER TABLE tbl_name CHANGE COLUMN c1 c1 VARCHAR(255), ALGORITHM=INPLACE, LOCK=NONE;
VARCHAR列所需的长度字节数必须保持不变。 对于大小为0到255字节的VARCHAR列,需要一个长度字节来对值进行编码。 对于大小为256字节或更大的VARCHAR列,需要两个长度字节。 因此, in-place ALTER TABLE仅支持将VARCHAR列大小从0增加到255个字节,或从256个字节增加到更大的大小。 in-place ALTER TABLE不支持将VARCHAR列的大小从小于256个字节增加到大小等于或大于256个字节。 在这种情况下,所需长度字节数从1变为2,这仅由表副本(ALGORITHM = COPY)支持。 例如,尝试使用in-place ALTER TABLE将单字节字符集的VARCHAR列大小从VARCHAR(255)更改为VARCHAR(256)会返回此错误:
ALTER TABLE tbl_name ALGORITHM=INPLACE, CHANGE COLUMN c1 c1 VARCHAR(256); ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.
注意:
VARCHAR 字段的长度字节 依赖于字符集的长度字节
不支持使用in-place ALTER TABLE减小VARCHAR大小。 减小VARCHAR大小需要表副本(ALGORITHM = COPY)。
ALTER TABLE tbl_name ALTER COLUMN col SET DEFAULT literal, ALGORITHM=INPLACE, LOCK=NONE;
仅修改表元数据。 默认列值存储在表的.frm文件中,而不是InnoDB数据字典中。
ALTER TABLE tbl ALTER COLUMN col DROP DEFAULT, ALGORITHM=INPLACE, LOCK=NONE;
ALTER TABLE table AUTO_INCREMENT=next_value, ALGORITHM=INPLACE, LOCK=NONE;
修改存储在内存中的值,而不是数据文件中的。
在使用复制或分片的分布式系统中,有时会将表的自动增量计数器重置为特定值。 插入表中的下一行使用其自动增量列的指定值。 您也可以在数据仓库环境中使用此技术,在该环境中,您定期清空所有表并重新加载它们,并从1重新启动自动增量序列
ALTER TABLE tbl_name MODIFY COLUMN column_name data_type NULL, ALGORITHM=INPLACE, LOCK=NONE;
以in-place 重建表。 数据进行了大量重组,使其成为一项昂贵的操作。
ALTER TABLE tbl_name MODIFY COLUMN column_name data_type NOT NULL, ALGORITHM=INPLACE, LOCK=NONE;
以in-place重建表。 STRICT_ALL_TABLES或STRICT_TRANS_TABLES SQL_MODE是操作成功所必需的。 如果列包含NULL值,则操作将失败。 服务器禁止更改可能导致参照完整性丢失的外键列。 请参见第13.1.8节“ALTER TABLE语法”。 数据进行了大量重组,使其成为一项昂贵的操作。
外键操作
增加和删除操作都支持 in-place的方式,不会重建表,只修改元数据,支持并行DML。
语法和使用事项
foreign_key_checks被禁用时支持INPLACE算法。 否则,仅支持COPY算法。
ALTER TABLE tbl1 ADD CONSTRAINT fk_name FOREIGN KEY index (col1) REFERENCES tbl2(col2) referential_actions;
ALTER TABLE tbl DROP FOREIGN KEY fk_name;
可以在启用或禁用foreign_key_checks选项的情况下在线执行删除外键。
如果您不知道特定表上的外键约束的名称,请发出以下语句并在CONSTRAINT子句中为每个外键查找约束名称:
SHOW CREATE TABLE table\G
或者 查询INFORMATION_SCHEMA.TABLE_CONSTRAINTS表并使用CONSTRAINT_NAME和CONSTRAINT_TYPE列标识外键名称。
您还可以在单个语句中删除外键及其关联的索引:
ALTER TABLE table DROP FOREIGN KEY constraint, DROP INDEX index;
注意:
如果要更改的表中已存在外键(即,它是包含FOREIGN KEY ... REFERENCE子句的子表),则其他限制适用于在线DDL操作,即使那些不直接涉及外键列的操作:
表操作
指定和转换字符集,启用或禁用表加密不支持并发DML,也不支持in-place 方式。其他的操作,例如 变更ROW_FORMAT,变更 KEY_BLOCK_SIZE,优化表,使用FORCE 选项重建都支持 in-place和并发DML。
语法和注意事项
ALTER TABLE tbl_name ROW_FORMAT = row_format, ALGORITHM=INPLACE, LOCK=NONE;
数据进行了大量重组,使其成为一项昂贵的操作。
ALTER TABLE tbl_name STATS_PERSISTENT=0, STATS_SAMPLE_PAGES=20, STATS_AUTO_RECALC=1, ALGORITHM=INPLACE, LOCK=NONE;
只修改表元数据
持久性统计信息包括STATS_PERSISTENT,STATS_AUTO_RECALC和STATS_SAMPLE_PAGES。
ALTER TABLE tbl_name CHARACTER SET = charset_name, ALGORITHM=INPLACE, LOCK=NONE;
如果新字符编码不同,则重建表。
ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name, ALGORITHM=COPY;
如果新字符编码不同,则重建表。
OPTIMIZE TABLE tbl_name;
具有FULLTEXT索引的表不支持in-place操作。 该操作使用INPLACE算法,但不允许使用ALGORITHM和LOCK语法。
ALTER TABLE tbl_name ENCRYPTION='Y', ALGORITHM=COPY;
具有FULLTEXT索引的表不支持in-place操作。 该操作使用INPLACE算法,但不允许使用ALGORITHM和LOCK语法。
ALTER TABLE tbl_name FORCE, ALGORITHM=INPLACE, LOCK=NONE;
从MySQL 5.6.17开始使用ALGORITHM = INPLACE。 具有FULLTEXT索引的表不支持ALGORITHM = INPLACE。
ALTER TABLE tbl_name ENGINE=InnoDB, ALGORITHM=INPLACE, LOCK=NONE;
从MySQL 5.6.17开始使用ALGORITHM = INPLACE。 具有FULLTEXT索引的表不支持ALGORITHM = INPLACE。
分区操作
除了大多数的ALTER TABLE分区子句,常规InnoDB表在线DDL操作规则适用于分区InnoDB表。
大多数ALTER TABLE分区子句不会通过与常规非分区InnoDB表相同的内部在线 DDL API。 因此,对ALTER TABLE分区条款的在线支持会有所不同。
无论使用何种在线DDL API,MySQL都会尝试尽可能减少数据复制和锁定。
TRUNCATE PARTITION, EXCHANGE PARTITION, ANALYZE PARTITION, CHECK PARTITION, REPAIR PARTITION 支持in-place和并发DML
其他操作都不支持并发DML
分区表上的非分区在线ALTER TABLE操作遵循适用于常规表的相同规则。 但是,ALTER TABLE对每个表分区执行在线操作,这会导致由于在多个分区上执行操作而对系统资源的需求增加。
14.13.2 在线DDL 性能和并发
在线DDL改进了MySQL操作的几个方面:
锁子句
默认情况下,MySQL在DDL操作期间使用尽可能少的锁定。 如果需要,可以指定LOCK子句以强制执行更严格的锁定。 如果LOCK子句指定的锁定级别低于特定DDL操作所允许的限制级别,则该语句将失败并显示错误。 LOCK子句在下面描述,按照最少限制的顺序:
允许并发查询和DML。
允许并发查询但是阻塞DML
允许尽可能多的并发(并发查询,DML或两者)。 省略LOCK子句与指定LOCK = DEFAULT相同。
当您知道DDL语句的默认锁定级别不会导致表的可用性问题时,请使用此子句。
Query OK, 0 rows affected (21.42 sec)
当在线DDL操作创建索引或更改表时,临时日志文件记录并发DML。 临时日志文件根据innodb_sort_buffer_size的值的要求进行扩展,最大值为innodb_online_alter_log_max_size指定的最大值。 如果临时日志文件超出大小限制,则在线DDL操作将失败,并且将回滚未提交的并发DML操作。 较大的innodb_online_alter_log_max_size设置允许在在线DDL操作期间使用更多DML,但是当表被锁定以应用记录的DML时,它还会延长DDL操作结束时的时间段。
如果操作需要很长时间并且并发DML修改表太多以至于临时日志文件的大小超过innodb_online_alter_log_max_size的值,则在线DDL操作将失败并出现DB_ONLINE_LOG_TOO_BIG错误。
重建表的在线DDL操作在创建索引期间将临时排序文件写入MySQL临时目录(Unix上的$TMPDIR,Windows上的%TEMP%或--tmpdir指定的目录)。 不会在包含原始表的目录中创建临时排序文件。 每个临时排序文件都足够大,可以容纳所有二级索引列以及聚簇索引的主键列。 一旦将内容合并到最终表或索引中,就会删除临时排序文件。 临时排序文件可能需要的空间等于表中的数据量加上索引。 如果使用了数据目录所在的文件系统上的所有可用磁盘空间,则重建表的联机DDL操作将报告错误。
如果MySQL临时目录不足以容纳排序文件,请将tmpdir设置为其他目录。 或者,使用innodb_tmpdir为在线DDL操作定义单独的临时目录。 MySQL 5.7.11中引入了此选项,以帮助避免由于大型临时排序文件而可能发生的临时目录溢出。
某些重建表的在线DDL操作会在与原始表相同的目录中创建临时中间表文件。 中间表文件可能需要等于原始表大小的空间。 中间表文件名以#sql-ib前缀开头,仅在在线DDL操作期间短暂出现。
innodb_tmpdir选项不适用于中间表文
14.13.4 使用在线DDL简化DDL语句
在引入在线DDL之前,通常的做法是将许多DDL操作组合到单个ALTER TABLE语句中。 因为每个ALTER TABLE语句都涉及复制和重建表,所以一次对同一个表进行多次更改会更有效,因为这些更改都可以通过表的单个重建操作完成。 缺点是涉及DDL操作的SQL代码难以维护,并很难在不同的脚本中重用。 如果每次特定更改都不同,则可能必须为每个稍微不同的方案构造新的复杂ALTER TABLE。
对于可以以in-place执行的DDL操作,您可以将它们分成单独的ALTER TABLE语句,以便更轻松地编写脚本和维护,而不会牺牲效率。 例如,您可能会采用一个复杂的语句,例如:
ALTER TABLE t1 ADD INDEX i1(c1), ADD UNIQUE INDEX i2(c2), CHANGE c4_old_name c4_new_name INTEGER UNSIGNED;
并将其分解为可以独立测试和执行的更简单的部分,例如:
ALTER TABLE t1 ADD INDEX i1(c1);
ALTER TABLE t1 ADD UNIQUE INDEX i2(c2);
ALTER TABLE t1 CHANGE c4_old_name c4_new_name INTEGER UNSIGNED NOT NULL;
您仍可以使用多部分ALTER TABLE语句:
14.13.5 在线DDL 失败条件
在线DDL操作失败通常是由于以下条件之一:
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3156759/ ,如需转载,请注明出处,否则将追究法律责任。