MySQL 5.6 - table 即使在使用 ALGORITHM=inplace 时也会锁定

MySQL 5.6 - table locks even when ALGORITHM=inplace is used

我是 运行 在 MySQL 5.6 数据库上 table 具有 6000 万行的以下 ALTER 命令:

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

尽管同时指定了 ALGORITHM=INPLACELOCK=NONE,但 table 会被锁定并实质上关闭应用程序,直到迁移完成。

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

根据我在 MySQL 文档中收集到的信息,此操作不应锁定 table。并且,如果 MySQL 无法在没有锁的情况下继续执行,则该命令应该失败。我将数据库升级到 MySQL 5.7 看它是否更好,但我在 5.7 上也遇到同样的问题。

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

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

未来:

8.0.12 有 ALTER TABLE .. ALGORITHM=INSTANT ADD COLUMN。参见 Discussion and ALTER Reference and Online DDL Reference

使用 INSTANT 算法添加列时存在以下限制:

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

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

如果您无法升级,请考虑 Percona 的 pt-online-schema-change 或新的竞争产品 gh-ost(使用二进制日志)。

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


检查 table

上的约束

如果 table.[=19 上存在 ON...CASCADE 或 ON...SET NULL 约束,则不允许 ALTER TABLE 子句 LOCK=NONE =]

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


table是否有外键关系?

An online DDL operation on a table in a foreign key relationship does not wait for a transaction executing on the other table in the foreign key relationship to commit or rollback. The transaction holds an exclusive metadata lock on the table it is updating and shared metadata lock on the foreign-key-related table (required for foreign key checking). The shared metadata lock permits the online DDL operation to proceed but blocks the operation in its final phase, when an exclusive metadata lock is required to update the table definition. This scenario can result in deadlocks as other transactions wait for the online DDL operation to finish.

来源: 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


首先从旧时间格式更改 tables

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

InnoDB tables created before MySQL 5.6 do not support ALTER TABLE ... ALGORITHM=INPLACE for tables that include temporal columns (DATE, DATETIME or TIMESTAMP) and have not been rebuilt using ALTER TABLE ... ALGORITHM=COPY. In this case, an ALTER TABLE ... ALGORITHM=INPLACE operation returns the following error:

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

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


检查 table 是否有分区

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

的分区状态

show table status;

寻找 'Engine' 不等于 InnoDB

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


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