MySQL 5.6 - 即使使用ALGORITHM=inplace,表锁仍然存在

18

我正在一个有6000万行记录的MySQL 5.6数据库中运行以下ALTER命令:

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

尽管指定了ALGORITHM = INPLACELOCK = NONE,但该表仍然被锁定,并且基本上会使应用程序停止,直到迁移完成。

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

根据我在MySQL文档中了解到的情况,此操作不应锁定表。而且,如果无法在没有锁定的情况下进行操作,MySQL应该失败该命令。我将数据库升级到MySQL 5.7以查看是否有所改善,但在5.7上也遇到了同样的问题。

这是一种预期的行为吗?我该如何找出问题出在哪里?


2
这不是InnoDB吗?你可能想要检查一下这个问题 - Til
嗨,杰弗里,我相信我最近遇到了同样的问题。在对大表进行耗时的DDL期间,该表会定期锁定以进行写操作。我们计划使用第三方工具来执行DDL。但是你是否曾经找出过即使指定了“ALGORITHM=INPLACE,LOCK=NONE;”,它为什么还会锁定表的原因? - Allen Hsu
1
@AllenHsu 我们无法解决这个问题,而且情况非常不可预测,所以最终不得不转向使用MySQL 8来解决这些问题,因为它提供了“ALGORITHM=INSTANT”的功能。我强烈建议进行切换:这让我们的生活变得更加轻松。 - jeffreyveon
感谢@jeffreyveon的及时回复。我会评估升级到MySQL 8的工作量并尝试一下。 - Allen Hsu
2个回答

12

我假设您在那个时间没有对该表进行其他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 语句中可以添加多个列。

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


1
我赞同使用pt-osc或gh-ost的建议。我刚刚数了一下我们的日志,发现我的雇主已经使用pt-osc进行了超过70,000次模式迁移。 - Bill Karwin

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

检查表上的约束条件

如果表上有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操作会返回以下错误:

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


检查表是否具有分区

分区会改变ALTER 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可能是一个选择,因为它提供了其他改进。

1
谢谢,这非常有用。您知道MySQL 8是否解决了一些提到的缺点(例如外键关系)吗? - jeffreyveon
@jeffreyveon 我个人没有使用过MySQL 8。然而,从以下链接到他们关于8.0版本限制的文档中可以看出,有一些共享、一些删除和一些不同的限制。https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-limitations.html - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接