16

ALTER在一个有 6000 万行的大表上的 MySQL 5.6 数据库上运行以下命令:

ALTER TABLE `large_table` ADD COLUMN `note` longtext NULL, 
ALGORITHM=INPLACE, LOCK=NONE;

尽管同时指定了ALGORITHM=INPLACELOCK=NONE,但该表仍会被锁定并基本上关闭应用程序,直到迁移完成。

我通过检查命令In_use输出中列的值来验证表确实被锁定。SHOW OPEN TABLES它被设置为1

根据我在 MySQL 文档中收集的信息,此操作不应锁定表。而且,如果没有锁就无法继续执行,MySQL 应该会导致命令失败。我将数据库升级到 MySQL 5.7 看看它是否更好,但我在 5.7 上也面临同样的问题。

这是预期的行为吗?我如何找出这里出了什么问题?

4

2 回答 2

9

我假设您几乎没有同时在该表上执行其他 DDL?

为未来:

8.0.12具有ALTER TABLE .. ALGORITHM=INSTANT. ADD COLUMN请参阅讨论ALTER 参考在线 DDL 参考

当使用 INSTANT 算法添加列时,以下限制适用:

  • 添加列不能与不支持 ALGORITHM=INSTANT 的其他 ALTER TABLE 操作在同一语句中组合。
  • 一列只能作为表格的最后一列添加。不支持将列添加到其他列中的任何其他位置。
  • 不能将列添加到使用 ROW_FORMAT=COMPRESSED 的表中。
  • 不能将列添加到包含 FULLTEXT 索引的表中。
  • 不能将列添加到临时表中。临时表仅支持 ALGORITHM=COPY。
  • 不能将列添加到驻留在数据字典表空间中的表中。
  • 添加列时不评估行大小限制。但是,在插入和更新表中的行的 DML 操作期间会检查行大小限制。

可以在同一个 ALTER TABLE 语句中添加多个列。

如果您无法升级,请考虑 Perconapt-online-schema-change或新的竞争产品gh-ost(使用 binlog)。

于 2019-02-18T18:45:18.283 回答
7

即使在使用 MySQL 5.6 锁定时,我也遇到过问题ALGORITHM=INPLACE, LOCK=NONE;。我将首先检查以下内容:


检查表上的约束

如果表上有 ON...CASCADE 或 ON...SET NULL 约束,则不允许使用 ALTER TABLE 子句 LOCK=NONE。

来源: https ://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html


表有外键关系吗?

在外键关系中的表上的在线 DDL 操作不会等待在外键关系中的另一个表上执行的事务提交或回滚。事务在它正在更新的表上持有独占元数据锁,并在外键相关表上持有共享元数据锁(外键检查需要)。共享元数据锁允许在线 DDL 操作继续进行,但在其最后阶段阻止该操作,此时需要独占元数据锁来更新表定义。当其他事务等待在线 DDL 操作完成时,这种情况可能会导致死锁。

来源: https ://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html

并在此处阅读有关元数据锁定的信息: https ://dev.mysql.com/doc/refman/5.6/en/metadata-locking.html


首先从旧时间格式更改表

如果您在 MySQL 5.6 之前使用 DATETIME 或 TIMESTAMP 字段创建了表,则需要将它们升级到 MySQL 5.6 的新格式。

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

错误 1846 (0A000):不支持 ALGORITHM=INPLACE。原因:无法更改列类型 INPLACE。尝试算法=复制。

来源: https ://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html


检查表是否有分区

分区改变了 alter table 规则的应用方式。检查表的分区状态

show table status;

寻找不等于 InnoDB 的“引擎”

资料来源: https ://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html#online-ddl-partitioning


最后,正如 Rick James 在他的回答中提到的,从 5.6 升级到 8.0 可能是一种选择,因为它提供了其他改进。

于 2019-07-21T23:16:35.177 回答