ITPub博客

首页 > 数据库 > > 14.13 InnoDB 在线 DDL

14.13 InnoDB 在线 DDL

作者:飘絮絮絮丶 时间:2020-05-11 14:29:17 0 删除 编辑

参考官方文档:
dev.mysql.com/doc/refma



在线DDL功能允许就地表更改或并发DML,或两者兼而有之。 此功能的好处包括:

  • 在繁忙的生产环境中提高响应能力和可用性,使表不可用几分钟或几小时是不切实际的。
  • 使用LOCK子句在DDL操作期间调整性能和并发性之间平衡的能力。 请参阅LOCK子句。
  • 与table-copy方法相比,使用的磁盘空间和I/O开销更少。



通常,您无需执行任何特殊操作即可启用在线DDL。 默认情况下,MySQL在允许的情况下执行操作,并尽可能少地锁定。


您可以使用ALTER TABLE语句的LOCK和ALGORITHM子句控制DDL操作的各个方面。 这些子句放在语句的末尾,用逗号分隔表和列。 例如:


ALTER TABLE tbl_name ADD PRIMARY KEY (column), ALGORITHM=INPLACE, LOCK=NONE;


LOCK子句可用于微调对表的并发访问程度。 ALGORITHM子句主要用于性能比较,并且在遇到任何问题时作为旧表复制行为的后备。 例如:


  • 为避免意外地使表不可用于读取,写入或两者,请在ALTER TABLE语句中指定一个子句,例如LOCK = NONE(允许读取和写入)或LOCK = SHARED(允许读取)。 如果请求的并发级别不可用,则操作立即停止。
  • 要比较性能,请运行ALGORITHM = INPLACE和ALGORITHM = COPY的语句。
  • 为避免使用复制表的ALTER TABLE操作来绑定服务器,请包括ALGORITHM = INPLACE。 如果语句不能使用in-place机制,则该语句立即停止。



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语句。


某些因素会影响此操作的性能,空间使用和语义。

  • 删除索引

    DROP INDEX name ON table;


    ALTER TABLE tbl_name DROP INDEX name;


    在删除索引时,该表仍可用于读写操作。 DROP INDEX语句仅在完成访问表的所有事务完成后才结束,因此索引的初始状态反映了表的最新内容。

  • 重命名 索引



ALTER TABLE tbl_name RENAME INDEX old_index_name TO new_index_name, ALGORITHM=INPLACE, LOCK=NONE;

  • 增加FULLTEXT 索引



CREATE FULLTEXT INDEX name ON table(column);
如果没有用户定义的FTS_DOC_ID列,则添加第一个FULLTEXT索引会重建表。 可以添加其他FULLTEXT索引而无需重建表。

  • 增加SPATIAL 索引


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更有效,因为:

  • ALGORITHM = INPLACE不需要undo 日志记录或关联的redo日志记录。 使用ALGORITHM = COPY的DDL语句,这些操作会增加开销。
  • 二级索引条目是预先排序的,因此可以按顺序加载。
  • 未使用更改缓冲区,因为没有随机访问插入到二级索引中。



如果服务器在创建新的聚簇索引时退出,则不会丢失任何数据,但必须使用进程中存在的临时表完成恢复过程。 由于很少在大型表上重新创建聚簇索引或重新定义主键,或者在此操作期间遇到系统崩溃,因此本手册不提供有关从此方案中恢复的信息。

  • 删除主键

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


  • 拓展 VARCHAR 字段大小

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重新启动自动增量序列

  • 将字段设置为NULL



ALTER TABLE tbl_name MODIFY COLUMN column_name data_type NULL, ALGORITHM=INPLACE, LOCK=NONE;


以in-place 重建表。 数据进行了大量重组,使其成为一项昂贵的操作。

  • 将字段置为 NOT NULL

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操作,即使那些不直接涉及外键列的操作:

  • 如果对父表的更改通过使用CASCADE或SET NULL参数的ON UPDATE或ON DELETE子句导致子表中的相关更改,则子表上的ALTER TABLE需要等待另一个事务提交
  • 同样,如果表是外键关系中的父表,即使它不包含任何FOREIGN KEY子句,如果INSER,UPDAE,DELETE语句导致子表ON UPDATE或 ON DELETE动作,它也需要等待ALTER TABLE完成。




表操作


指定和转换字符集,启用或禁用表加密不支持并发DML,也不支持in-place 方式。其他的操作,例如 变更ROW_FORMAT,变更 KEY_BLOCK_SIZE,优化表,使用FORCE 选项重建都支持 in-place和并发DML。


语法和注意事项

  • 变更 ROW_FORMAT

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语法。


  • 使用FORCE 选项重建表



ALTER TABLE tbl_name FORCE, ALGORITHM=INPLACE, LOCK=NONE;


从MySQL 5.6.17开始使用ALGORITHM = INPLACE。 具有FULLTEXT索引的表不支持ALGORITHM = INPLACE。




  • 执行一个"null" 重建

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操作的几个方面:


  • 访问表的应用程序响应更快,因为在DDL操作正在进行时,表上的查询和DML操作可以继续进行。 减少锁定和等待MySQL服务器资源可以实现更高的可伸缩性,即使对于不参与DDL操作的操作也是如此。
  • in-place 操作可避免与表复制方法关联的磁盘I / O和CPU周期,从而最大限度地减少数据库的总体负载。 最小化负载有助于在DDL操作期间保持良好的性能和高吞吐量。
  • in-place 操作比表复制操作向缓冲池中读取更少的数据,这减少了从内存中清除频繁访问的数据量。 清除频繁访问的数据可能会导致DDL操作后暂时性能下降。





锁子句


默认情况下,MySQL在DDL操作期间使用尽可能少的锁定。 如果需要,可以指定LOCK子句以强制执行更严格的锁定。 如果LOCK子句指定的锁定级别低于特定DDL操作所允许的限制级别,则该语句将失败并显示错误。 LOCK子句在下面描述,按照最少限制的顺序:

  • LOCK=NONE


允许并发查询和DML。

  • LOCK=SHARD


允许并发查询但是阻塞DML

  • LOCK=DEFAULT


允许尽可能多的并发(并发查询,DML或两者)。 省略LOCK子句与指定LOCK = DEFAULT相同。

当您知道DDL语句的默认锁定级别不会导致表的可用性问题时,请使用此子句。

  • LOCK=EXCLUSIVE



    阻塞并发查询和DML


    如果主要关注点是在尽可能短的时间内完成DDL操作,则使用此子句,并且不需要并发查询和DML访问。 如果服务器应该处于空闲状态,您也可以使用此子句,以避免意外的表访问

    在线DDL 和元数据锁


    在线DDL操作可视为分为三个阶段:


  • 阶段1:初始化
    在初始化阶段,服务器确定在操作期间允许多少并发,同时考虑存储引擎功能,语句中指定的操作以及用户指定的ALGORITHM和LOCK选项。 在此阶段,将采用共享的可升级元数据锁来保护当前表定义。
  • 阶段2:执行
    在此阶段,语句被准备并被执行。 元数据锁是否升级为独占取决于初始化阶段评估的因素。 如果需要独占元数据锁定,则仅在语句准备期间进行短暂锁定。
  • 阶段3:提交表定义
    在提交表定义阶段,元数据锁升级为独占以驱逐旧表定义并提交新表定义。 一旦被授予,独占元数据锁定的持续时间很短。






    由于上面列出的独占元数据锁定要求,在线DDL操作可能必须等待在表上持有元数据锁定的并发事务的提交或回滚。 在DDL操作之前或期间启动的事务可以在要更改的表上持有元数据锁。 在长时间运行或非活动事务的情况下,在线DDL操作可能会等待独占元数据锁定而超时。 此外,在线DDL操作请求的挂起的独占元数据锁会阻止表上的后续事务。


    以下示例演示了等待独占元数据锁定的联机DDL操作,以及挂起的元数据锁如何阻止表上的后续事务。


    会话1:


    mysql> CREATE TABLE t1 (c1 INT) ENGINE=InnoDB;
    mysql> START TRANSACTION;
    mysql> SELECT * FROM t1;


    会话1 的SELECT语句在表t1上有共享元数据锁。


    会话2:
    mysql> ALTER TABLE t1 ADD COLUMN x INT, ALGORITHM=INPLACE, LOCK=NONE;


    会话2中的在线DDL操作(需要对表t1进行独占元数据锁定以提交表定义更改)必须等待会话1事务提交或回滚


    会话3:
    mysql> SELECT * FROM t1;


    会话3中发出的SELECT语句被阻止,等待会话2中ALTER TABLE操作请求的独占元数据锁。

    您可以使用SHOW FULL PROCESSLIST来确定事务是否在等待元数据锁定。
    元数据锁定信息也通过Performance Schema metadata_locks表公开,该表提供有关会话之间的元数据锁定依赖关系,会话正在等待的元数据锁定以及当前持有元数据锁定的会话的信息。



    在线DDL 性能


    DDL操作的性能很大程度上取决于操作是否in-place执行以及是否重建表。


    要评估DDL操作的相对性能,可以使用ALGORITHM = INPLACE将结果与使用ALGORITHM = COPY的结果进行比较。 或者,您可以将结果与old_alter_table禁用和启用进行比较。


    对于修改表数据的DDL操作,您可以通过查看命令完成后显示的“受影响的行”值来确定DDL操作是in-place更改还是执行表副本。 例如:


  • 变更字段的默认值(很快,不影响表数据)
    Query OK, 0 rows affected (0.07 sec)
  • 增加一个索引(会花费时间,但是表不会被拷贝,显示0行被影响)

Query OK, 0 rows affected (21.42 sec)

  • 变更字段的数据类型(需要大量时间,需要重建表的所有行):
    Query OK, 1671168 rows affected (1 min 35.54 sec)

    在大型表上运行DDL操作之前,请检查操作是快还是慢,如下所示:


    1.克隆表结构
    2.使用少量数据填充克隆表。
    3.在克隆表上执行DDL
    4.检查“受影响的行”值是否为零。 非零值表示操作复制表数据,这可能需要特殊规划。 例如,您可以在计划停机期间执行DDL操作,也可以在每个复制从服务器上执行一次DDL操作




    注意:
    为了更好地理解与DDL操作相关的MySQL处理,请在DDL操作之前和之后检查与InnoDB相关的Performance Schema和INFORMATION_SCHEMA表,以查看物理读取,写入,内存分配等的数量。



    由于记录由并发DML操作所做的更改所涉及的一些处理工作,然后在最后应用这些更改,因此在线DDL操作可能比阻止来自其他会话的表访问的表复制机制花费更长的时间。 原始性能的降低与使用该表的应用程序的更好响应性相平衡。 在评估更改表结构的技术时,请考虑最终用户对性能的感知,这取决于诸如网页加载时间等因素。



    14.13.3 在线DDL 空间需求


    在线DDL 操作有下列空间需求:
  • 临时日志文件的空间



当在线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语句:

  • 必须以特定顺序执行的操作,例如创建索引,后跟使用该索引的外键约束。
  • 所有使用相同特定LOCK子句的操作,您希望作为一个组成功或失败。
  • 无法in-place执行的操作,即仍使用表复制方法的操作。
  • 为其指定ALGORITHM = COPY或old_alter_table = 1的操作,以强制执行表复制行为(如果需要),以便在特定方案中实现精确的向后兼容性。



14.13.5 在线DDL 失败条件


在线DDL操作失败通常是由于以下条件之一:

  • ALGORITHM子句指定与特定类型的DDL操作或存储引擎不兼容的算法。
  • LOCK子句指定与特定类型的DDL操作不兼容的低锁定度(SHARED或NONE)。
  • 等待表上的独占锁时发生超时,这可能在DDL操作的初始阶段和最后阶段期间短暂需要。
  • MySQL在创建索引期间在磁盘上写入临时排序文件时 tmpdir或innodb_tmpdir文件系统用尽磁盘空间。
  • 该操作需要很长时间,并发DML会对表进行修改,以至于临时在线日志的大小超过了innodb_online_alter_log_max_size配置选项的值。 此情况会导致DB_ONLINE_LOG_TOO_BIG错误。



  • 并发DML对原始表定义的表进行允许的更改,但不对新表进行更改。 当MySQL尝试应用并发DML语句中的所有更改时,操作仅在最后失败。 例如,您可以在创建唯一索引时将重复值插入到列中,也可以在该列上创建主键索引时将NULL值插入列中。 并发DML所做的更改优先,并且ALTER TABLE操作有效地回滚。



    14.13.6 在线DDL 限制


    以下限制适用于在线DDL操作:
  • 在TEMPORARY TABLE上创建索引时,该表被复制。
  • 如果在表上有ON ... CASCADE或ON ... SET NULL约束,则不允许ALTER TABLE子句LOCK = NONE。
  • 在在线DDL操作完成之前,它必须等待保存表上的元数据锁的事务提交或回滚。 在线DDL操作可能在其执行阶段短暂地要求对表进行独占元数据锁定,并且在更新表定义时始终在操作的最后阶段需要一次锁定。 因此,在表上保存元数据锁的事务可能导致在线DDL操作被阻止。 在表上保存元数据锁的事务可能已在在线DDL操作之前或期间启动。 在表上保存元数据锁的长时间运行或非活动事务可能导致在线DDL操作超时。
  • 外键关系中的表上的在线DDL操作不会等待在外键关系中的另一个表上执行的事务提交或回滚。 该事务在其正在更新的表上保持独占元数据锁,并在外键相关表上保持共享元数据锁(外键检查所需)。 共享元数据锁允许在线DDL操作继续进行,但在更新表定义需要独占元数据锁时,在最后阶段阻止操作。 此方案可能导致死锁,因为其他事务等待在线DDL操作完成。


  • 运行在线DDL操作时,运行ALTER TABLE语句的线程应用从其他连接线程在同一表上并发运行的DML操作的在线日志。 应用DML操作时,可能会遇到重复的key输入错误(ERROR 1062(23000):Duplicate entry),即使重复条目只是临时条目,也会被在线日志中的后续条目恢复。 这类似于InnoDB中的外键约束检查的想法,其中约束必须在事务期间保持。
  • InnoDB表的OPTIMIZE TABLE映射到ALTER TABLE操作,以重建表并更新索引统计信息并释放聚簇索引中未使用的空间。 辅助索引的创建效率不高,因为key是按照它们在主键中出现的顺序插入的。 支持OPTIMIZE TABLE,增加了在线DDL支持,用于重建常规和分区的InnoDB表。


  • 在MySQL 5.6之前创建的包含时态列(DATE,DATETIME或TIMESTAMP)且未使用ALGORITHM = COPY重建的表不支持ALGORITHM = INPLACE。 在这种情况下,ALTER TABLE ... ALGORITHM = INPLACE操作返回以下错误:

    ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

  • 以下限制通常适用于涉及重建表的大型表上的在线DDL操作:
  1. 没有机制可以暂停在线DDL操作或限制在线DDL操作的I / O或CPU使用率。
  2. 如果操作失败,则回滚在线DDL操作可能很昂贵。
  3. 长时间运行的在线DDL操作可能导致复制滞后。 在从服务器上运行之前,在线DDL操作必须在主服务器上完成运行。 此外,在主服务器上同时处理的DML仅在从服务器上的DDL操作完成后才在从服务器上处理。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3156759/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-09-09

  • 博文量
    2646
  • 访问量
    42316