MySQL 未能更改正在主动写入的 TABLE
MySQL failing to ALTER TABLE which is being actively written to
在我的应用程序的一个用例中,我有两个并发的 MySQL 连接:
- 一个积极写入名为
T
的 table(实际上,不断更新此 table 中的一行),并且
- 另一个针对完全相同的 table 执行 DDL(
ALTER TABLE
,添加 8 个新列并将一列从 varchar(80)
扩展到 varchar(2000)
)。 DDL 有望最终完成。
UPDATE
DML 中的列不受 DDL 的影响。
table 仅包含一行(第 UPDATE
行)。
分析
当涵盖此用例的集成测试是 运行 时,我观察到的是测试超时(table 被如此积极地写入,因此 DDL 永远不会完成),但是仅适用于 MySQL 5.7。通常情况下,测试预计会在我们的硬件上在 30 秒内完成(这确实发生在 MySQL 5.6 和 8.0 上),但对于 MySQL 5.7 甚至 200 秒都不够。我尝试了不同的 ALGORITHM
和 LOCK
值(参见 13.1.8 ALTER TABLE Syntax),但没有成功。
当我分析我的应用程序时(MySQL 5.7 案例),我观察到 99% 的 CPU 时间都花在从套接字读取(即等待 MySQL 响应 table 已被更改),但数据库实例对我来说是一种黑盒子——当然我有performance_schema
已启用并且可以 运行 对其进行查询,但我不知道我要查找的确切信息。
合成
与此同时,我未能将问题简化为最小的独立单元测试——我唯一观察到的是 3x 到 10x 与其他 MySQL 版本相比,MySQL 的测试运行时间增加了 5.7,但 DDL不会永远挂起:
所有 MySQL 版本都是 Windows 或 Debian Linux 从 www.mysql.com 下载,对 my.cnf
或官方 Docker 图片进行了极小的改动。
问题:
- MySQL在技术上真的可以永远延迟
ALTER TABLE
DDL的执行吗?或者我观察到的只是一个非常繁忙的数据库实例?有没有可能
- 请求中断地执行
ALTER TABLE
,即。 e.如果超过特定的超时时间,数据库将返回一个错误,或者
- 强制暂停所有其他连接,这些连接甚至可能对 table 或其某些行设置
SHARED
锁定,以便它们不会在 DDL 执行时进行干预?
- 在处理原来的集成测试超时时,如何从MySQL方面进一步诊断?
TL;DR — 提交您的事务以解锁您的 ALTER TABLE.
是的,ALTER TABLE 可以长时间阻塞。它可能看起来像永远。其实就是lock_wait_timeout的值,默认是31536000秒,也就是365天
在 MySQL 中,像 ALTER TABLE 这样的 DDL 语句需要在 table 上独占 metadata lock。目的是确保您不会同时从两个并发会话中更改 TABLE。
像 SELECT、INSERT、UPDATE、DELETE 这样的 DML 语句也持有 "shared" 元数据锁。共享锁可以由多个会话并发持有,但阻止独占锁,因为独占锁要求它们是唯一持有 table 上任何类型锁的人。
文档状态:
This locking approach has the implication that a table that is being used by a transaction within one session cannot be used in DDL statements by other sessions until the transaction ends.
DML 语句持有元数据锁的目的是它们可以保留 table 的重复table-读取视图,而不必担心另一个会话正在执行 DROP TABLE 或改变 TABLE 以妥协他们对 table 的看法。这种锁定是必要的,因为 MySQL 没有版本化元数据 (they are gradually working toward that)。
这意味着具有 运行 简单 SELECT 且未提交的事务将阻止需要锁定更改的 DROP TABLE 或 ALTER TABLE。
在线 DDL 的引入有些细微差别。
Online DDL Performance and Concurrency 更详细地描述了 ALTER TABLE 通过获取共享元数据锁开始,因此未提交的事务不会阻止它。但是下一阶段可能会将共享元数据锁升级为独占元数据锁,如果 ALTER TABLE 更改的性质需要的话。此时,锁获取被阻塞,因为另一个事务还持有自己的元数据锁。
在线 DDL 并不适用于所有类型的 ALTER TABLE 操作;有些仍然需要独占锁。例如,您正在更改数据类型,需要排他锁。有关详细信息,请参阅 Online DDL Overview。
在我的应用程序的一个用例中,我有两个并发的 MySQL 连接:
- 一个积极写入名为
T
的 table(实际上,不断更新此 table 中的一行),并且 - 另一个针对完全相同的 table 执行 DDL(
ALTER TABLE
,添加 8 个新列并将一列从varchar(80)
扩展到varchar(2000)
)。 DDL 有望最终完成。
UPDATE
DML 中的列不受 DDL 的影响。
table 仅包含一行(第 UPDATE
行)。
分析
当涵盖此用例的集成测试是 运行 时,我观察到的是测试超时(table 被如此积极地写入,因此 DDL 永远不会完成),但是仅适用于 MySQL 5.7。通常情况下,测试预计会在我们的硬件上在 30 秒内完成(这确实发生在 MySQL 5.6 和 8.0 上),但对于 MySQL 5.7 甚至 200 秒都不够。我尝试了不同的 ALGORITHM
和 LOCK
值(参见 13.1.8 ALTER TABLE Syntax),但没有成功。
当我分析我的应用程序时(MySQL 5.7 案例),我观察到 99% 的 CPU 时间都花在从套接字读取(即等待 MySQL 响应 table 已被更改),但数据库实例对我来说是一种黑盒子——当然我有performance_schema
已启用并且可以 运行 对其进行查询,但我不知道我要查找的确切信息。
合成
与此同时,我未能将问题简化为最小的独立单元测试——我唯一观察到的是 3x 到 10x 与其他 MySQL 版本相比,MySQL 的测试运行时间增加了 5.7,但 DDL不会永远挂起:
所有 MySQL 版本都是 Windows 或 Debian Linux 从 www.mysql.com 下载,对 my.cnf
或官方 Docker 图片进行了极小的改动。
问题:
- MySQL在技术上真的可以永远延迟
ALTER TABLE
DDL的执行吗?或者我观察到的只是一个非常繁忙的数据库实例?有没有可能- 请求中断地执行
ALTER TABLE
,即。 e.如果超过特定的超时时间,数据库将返回一个错误,或者 - 强制暂停所有其他连接,这些连接甚至可能对 table 或其某些行设置
SHARED
锁定,以便它们不会在 DDL 执行时进行干预?
- 请求中断地执行
- 在处理原来的集成测试超时时,如何从MySQL方面进一步诊断?
TL;DR — 提交您的事务以解锁您的 ALTER TABLE.
是的,ALTER TABLE 可以长时间阻塞。它可能看起来像永远。其实就是lock_wait_timeout的值,默认是31536000秒,也就是365天
在 MySQL 中,像 ALTER TABLE 这样的 DDL 语句需要在 table 上独占 metadata lock。目的是确保您不会同时从两个并发会话中更改 TABLE。
像 SELECT、INSERT、UPDATE、DELETE 这样的 DML 语句也持有 "shared" 元数据锁。共享锁可以由多个会话并发持有,但阻止独占锁,因为独占锁要求它们是唯一持有 table 上任何类型锁的人。
文档状态:
This locking approach has the implication that a table that is being used by a transaction within one session cannot be used in DDL statements by other sessions until the transaction ends.
DML 语句持有元数据锁的目的是它们可以保留 table 的重复table-读取视图,而不必担心另一个会话正在执行 DROP TABLE 或改变 TABLE 以妥协他们对 table 的看法。这种锁定是必要的,因为 MySQL 没有版本化元数据 (they are gradually working toward that)。
这意味着具有 运行 简单 SELECT 且未提交的事务将阻止需要锁定更改的 DROP TABLE 或 ALTER TABLE。
在线 DDL 的引入有些细微差别。
Online DDL Performance and Concurrency 更详细地描述了 ALTER TABLE 通过获取共享元数据锁开始,因此未提交的事务不会阻止它。但是下一阶段可能会将共享元数据锁升级为独占元数据锁,如果 ALTER TABLE 更改的性质需要的话。此时,锁获取被阻塞,因为另一个事务还持有自己的元数据锁。
在线 DDL 并不适用于所有类型的 ALTER TABLE 操作;有些仍然需要独占锁。例如,您正在更改数据类型,需要排他锁。有关详细信息,请参阅 Online DDL Overview。