我正在具有6,000万行的大型表上的MySQL 5.6数据库上运行以下ALTER
命令:
ALTER TABLE `large_table` ADD COLUMN `note` longtext NULL,
ALGORITHM=INPLACE, LOCK=NONE;
尽管同时指定了ALGORITHM=INPLACE
和LOCK=NONE
,但该表被锁定并实质上关闭了应用程序,直到迁移完成。
我通过检查In_use
命令输出上的SHOW OPEN TABLES
列的值来验证该表确实已锁定。它设置为1
。
从我在MySQL文档中收集的信息来看,此操作不应锁定表。而且,如果没有锁,MySQL无法执行该命令,则该命令将失败。我将数据库升级到MySQL 5.7,看它是否更好,但我在5.7上也遇到了同样的问题。
这是预期的行为吗?我如何找出这里出了什么问题?
答案 0 :(得分:2)
我假设您不是在同一时间在该表上执行其他DDL吗?
为了未来:
8.0.12具有ALTER TABLE .. ALGORITHM=INSTANT
的{{1}}。参见Discussion和ALTER Reference和Online DDL Reference
使用INSTANT算法添加列时,存在以下限制:
可以在同一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可能是一个选择,因为它提供了其他改进。