代码之家  ›  专栏  ›  技术社区  ›  Bass

MySQL无法更改正在主动写入的表

  •  5
  • Bass  · 技术社区  · 7 年前

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

    • 主动写入名为 T
    • 另一个对同一个表执行DDL( ALTER TABLE ,添加8个新列并扩展一个列 varchar(80) varchar(2000) ). 预计DDL最终会完成。

    UPDATE DML是 受DDL的影响。

    更新 ‘d’)。

    分析

    当运行一个包含这个用例的集成测试时,我观察到的是一个测试超时(该表被如此积极地写入,以致DDL永远不会完成),但仅限于 MySQL数据库 MySQL数据库 5.6和8.0),但是 5.7即使200秒也不够。我尝试过不同的 ALGORITHM LOCK 值(请参见 13.1.8 ALTER TABLE Syntax ),没有运气。

    MySQL数据库 5.7的情况下),我观察到99%的CPU时间都花在从一个套接字读取数据上(即等待 MySQL数据库 performance_schema 已启用并可以对其运行查询,但我不知道要查找的确切信息。

    同时,我未能将问题简化为最小的自包含单元测试——我观察到的唯一问题是 3倍 10倍 测试所用时间的增加 5.7与其他 MySQL数据库

    enter image description here

    全部 MySQL数据库 版本是的库存版本 窗户 Debian Linux系统 www.mysql.com 只需对 my.cnf ,或官员 码头工人 图像。

    问题:

    1. 从技术上来说 MySQL数据库 推迟执行 永远的DDL?或者我观察到的只是一个非常繁忙的数据库实例?有没有可能
      • 请求 可中断地执行,即如果超过某个超时,则数据库返回一个错误,或者
      • 强制所有其他可能放置 SHARED 锁定表或其某些行以暂停,以便它们在执行DDL时不进行干预?
    2. 在处理原始集成测试超时时,如何从 MySQL数据库
    1 回复  |  直到 7 年前
        1
  •  5
  •   Bill Karwin    7 年前

    TL;DR提交事务以解除锁定ALTER表。


    是的,ALTER TABLE可以阻塞很长时间。它看起来像是永远的。它实际上是 lock_wait_timeout ,默认为31536000秒,即365天。

    在MySQL中,像ALTER TABLE这样的DDL语句需要一个 metadata lock

    像SELECT、INSERT、UPDATE、DELETE这样的DML语句也持有“shared”元数据锁。共享锁可以由多个会话同时持有,但会阻止独占锁,因为独占锁要求它们是唯一一个持有表上任何类型锁的会话。

    文件说明:

    持有元数据锁的DML语句的目的是,它们可以保留表的可重复读取视图,而不必担心另一个会话正在执行DROP table或ALTER table以损害它们的表视图。此锁定是必需的,因为MySQL没有版本化的元数据( they are gradually working toward that ).

    这意味着运行了简单SELECT但未提交的事务将阻塞需要锁定更改的DROP表或ALTER表。

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

    Online DDL Performance and Concurrency 更详细地描述了ALTER表从获取共享元数据锁开始,因此未提交的事务不会阻止它。但是,如果ALTER TABLE更改的性质需要,下一阶段可能会将共享元数据锁升级为独占元数据锁。此时,锁获取被阻止,因为另一个事务仍然持有自己的元数据锁。

    联机DDL并不适用于所有类型的ALTER TABLE操作;有些仍然需要独占锁。例如,更改数据类型需要一个独占锁。见 Online DDL Overview