草庐IT

java - MySQL 无法更改正在主动写入的 TABLE

coder 2023-10-05 原文

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

  • 主动写入名为 T 的表(实际上,不断更新该表中的一行),以及
  • 另一个对同一个表执行 DDL(ALTER TABLE,添加 8 个新列并将一列从 varchar(80) 扩展到 varchar( 2000))。 DDL 预计最终会完成。

UPDATE DML 中的列不受 DDL 的影响。

该表仅包含一行(正在UPDATE的行)。

分析

当运行涵盖此用例的集成测试时,我观察到测试超时(正在积极写入表,因此 DDL 永远不会完成),但仅适用于 MySQL 5.7.通常,测试预计在我们的硬件上在 30 秒内完成(这确实发生在 MySQL 5.6 和 8.0 上),但对于 MySQL 5.7 甚至 200 秒是不够的.我尝试了不同的 ALGORITHMLOCK 值(参见 13.1.8 ALTER TABLE Syntax ),但没有成功。

当我分析我的应用程序时(MySQL 5.7 案例),我观察到 99% 的 CPU 时间花在从套接字读取(即等待 MySQL 响应表已被更改),但数据库实例对我来说是一种黑盒子——当然我启用了 performance_schema 并且可以对其运行查询,但我不知道哪些确切信息我在找。

合成

与此同时,我未能将问题减少到最小的独立单元测试——我唯一观察到的是测试增加了 3x10x MySQL 5.7 与其他 MySQL 版本相比的运行时间,但 DDL 不会永远挂起:

所有 MySQL 版本都是从 www.mysql.com 下载的 WindowsDebian Linux 库存版本对 my.cnf 或官方 Docker 图像进行最少的更改。

问题:

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

最佳答案

TL;DR — 提交您的事务以解锁您的 ALTER TABLE。


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

在 MySQL 中,像 ALTER TABLE 这样的 DDL 语句需要独占 metadata lock在 table 上。目的是确保您不会同时从两个并发 session 更改 TABLE。

DML 语句,如 SELECT、INSERT、UPDATE、DELETE 也持有“共享”元数据锁。共享锁可以由多个 session 并发持有,但会阻塞排他锁,因为排他锁要求它们是唯一持有表上任何类型锁的人。

文档状态:

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 语句持有元数据锁的目的是,它们可以保留表的可重复读取 View ,而不必担心另一个 session 正在执行 DROP TABLE 或 ALTER TABLE 以破坏它们的 TableView 。这种锁定是必要的,因为 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了解详情。

关于java - MySQL 无法更改正在主动写入的 TABLE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51902557/

有关java - MySQL 无法更改正在主动写入的 TABLE的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  4. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  5. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  6. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  7. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  8. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  9. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  10. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

随机推荐