MySQL无法正在写入的ALTER TABLE

Bas*_*ass 6 java mysql innodb jdbc

在我的应用程序的一个用例中,我有两个并发的MySQL连接:

  • 一个主动写入一个名为的表T(实际上,不断更新此表中的一行),和
  • 另一个针对非常相同的表执行DDL( ALTER TABLE,添加8个新列和从延伸的一个列varchar(80)varchar(2000)).预计DDL最终会完成.

在列UPDATEDML都不会受到DDL.

该表只包含一行(一行是UPDATE'd).

分析

当运行涵盖此用例的集成测试时,我观察到的是测试超时(表正在如此主动地写入,以便DDL永远不会完成),但仅适用于MySQL 5.7.通常情况下,测试预计会在30秒内在我们的硬件上完成(对于MySQL 5.6和8.0 确实会发生),但对于MySQL 5.7甚至200秒是不够的.我已经尝试了不同的ALGORITHMLOCK值(见13.1.8 ALTER TABLE语法),没有运气.

当我描述我的应用程序(MySQL 5.7案例)时,我发现99%的CPU时间用于从套接字读取(即等待MySQL响应表已被更改),但数据库实例是一种黑色盒子给我 - 当然我已经performance_schema启用并可以对它运行查询,但我不知道我正在寻找哪些确切的信息.

合成

与此同时,我没有将问题简化为最小的自包含单元测试 - 我发现,与其他MySQL版本相比,MySQL 5.7 测试所用时间增加了3倍10倍,但DDL没有永远挂起:

在此输入图像描述

所有MySQL版本都是Windows版的库存版或从www.mysql.com下载的Debian Linux版本,只有极少的更改或官方Docker镜像.my.cnf

问题:

  1. 从技术上讲,MySQL是否可以ALTER TABLE永久延迟DDL 的执行?或者我正在观察的只是一个非常繁忙的数据库实例?是否有可能
    • 请求以ALTER TABLE可中断的方式执行,即如果超过某个超时,则数据库返回错误,或者
    • 强制所有其他连接,甚至可能SHARED锁定表或其某些行暂停,以便在执行DDL时它们不会干预?
  2. 在处理原始集成测试超时时,如何从MySQL端进一步诊断情况?

Bil*_*win 5

TL; DR - 提交您的事务以取消阻止您的ALTER TABLE.


是的,ALTER TABLE可以阻塞很长时间.它似乎永远.它实际上是lock_wait_timeout的值,默认为31536000秒,或365天.

在MySQL中,像ALTER TABLE这样的DDL语句需要对表进行独占元数据锁定.目的是确保您不会同时从两个并发会话中使用ALTER TABLE.

像SELECT,INSERT,UPDATE,DELETE这样的DML语句也包含"共享"元数据锁.共享锁可以由多个会话同时保留,但阻塞独占锁,因为排它锁要求它们是唯一一个在表上保存任何类型锁的锁.

文件说明:

这种锁定方法的含义是,在事务结束之前,其他会话不能在DDL语句中使用一个会话中的事务正在使用的表.

持有元数据锁的DML语句的目的是使它们可以保留它们对表的可重复读取视图,而不必担心另一个会话正在执行DROP TABLE或ALTER TABLE来破坏它们对表的视图.这种锁定是必要的,因为MySQL没有版本化的元数据(他们正在逐步努力).

这意味着运行简单SELECT并且不提交的事务将阻止需要锁定更改的DROP TABLE或ALTER TABLE.

在线DDL的引入有一些细微差别.

在线DDL性能和并发性更详细地描述了ALTER TABLE通过获取共享元数据锁开始,因此未提交的事务不会阻止它.但是,如果ALTER TABLE更改的性质需要,则下一阶段可以将共享元数据锁升级为独占元数据锁.此时,锁定获取被阻止,因为另一个事务仍然拥有自己的元数据锁定.

在线DDL不适用于每种类型的ALTER TABLE操作; 有些人还需要独家锁.例如,正如您所做的那样更改数据类型需要独占锁定.有关详细信息,请参阅在线DDL概述

  • 我建议你查看`information_schema.innodb_trx加入information_schema.processlist on processlist.id = innodb_trx.trx_mysql_thread`或`show engine innodb status`当你看到DDL需要很长时间,并弄清楚它是否在等待锁定,或者是否它正在执行. (2认同)