MySQL 5.6-即使使用ALGORITHM = inplace,表也会锁定

时间:2019-02-13 09:47:17

标签: mysql table-locking

我正在具有6,000万行的大型表上的MySQL 5.6数据库上运行以下ALTER命令:

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上也遇到了同样的问题。

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

2 个答案:

答案 0 :(得分:2)

我假设您不是在同一时间在该表上执行其他DDL吗?

为了未来:

8.0.12具有ALTER TABLE .. ALGORITHM=INSTANT的{​​{1}}。参见DiscussionALTER ReferenceOnline DDL Reference

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

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

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

如果您无法升级,请考虑使用Percona的ADD COLUMN或竞争性新产品pt-online-schema-change(使用binlog)。

答案 1 :(得分:1)

即使使用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操作将返回以下错误:

     

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

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


检查表是否具有分区

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

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