草庐IT

Mysql - 序列化失败 : 1213 Deadlock found when try to get lock; try restarting transaction

coder 2023-10-06 原文

我有菜单类别产品 表。我正在使用 mysql 5.5,所有表都是 innoDB 并且在所有情况下 id 都是具有自动增量的主键 (int)。

menus table
id, name, status

categories table
id, menu_id, name

products table
id, menu_id, category_id, status, name, url, content

多个脚本可以并行运行,执行包含以下逻辑的同一个php文件。

START TRANSACTION;
SET autocommit = 0;

LOCK TABLES products WRITE, categories WRITE, menus WRITE;

SELECT 
  p.`id`,
  p.`name`,
  p.`url`,
  p.`status`,
  c.`id` cat_id,
  c.`name` cat_name,
  m.`id` `menu_id`,
  m.`name` menu_name
FROM
  products p 
  LEFT JOIN categories c 
    ON p.`subcategory_id` = c.`id` 
  LEFT JOIN menus m 
    ON p.`menu_id` = m.`id` 
   WHERE p.`status` = 0 LIMIT 1

如果找到选择结果后,它的状态更新为1(否则我回滚并释放锁)

UPDATE products SET status = 1 WHERE id = [product_id];

如果最后一次查询成功我运行

COMMIT();
UNLOCK TABLES;

否则

ROLLBACK();
UNLOCK TABLES;

在此之后,脚本向该产品的 url 发出 curl 请求以从中获取一些内容并相应地更新产品的行

// making curl request (might take a few dozen seconds, because proxy is being used and sometimes because of proxy failure the request is attempted again)

trying to update the products table 

    UPDATE products SET content = [received content], status = 2 WHERE id = [product_id]

因此,脚本在上述表上获取 X 锁,从产品表中获取状态为 0(表示 - TODO)的一行,尝试将其状态设置为 1(表示待处理),然后解锁表。之后尝试在 php 中执行一些逻辑,最后尝试更新产品表 - 将内容列和状态更新为 2(表示完成)。

如果我并行运行 5 个脚本,在最后一步运行几分钟后(将产品更新为“完成”),我会收到此错误

Error: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when try to get lock; try restarting transaction

我理解当 2 个事务等待对方以相反顺序更新相同行时死锁的一般概念,但是我无法弄清楚在这种情况下死锁的原因。我的意思是脚本正在工作并以相同的顺序锁定表,所以如果一个脚本锁定了 products(和其他)表,获取独占锁,另一个脚本应该在队列中等待这些锁释放,所以它不应该导致死锁。
另一方面,每个脚本都选择状态为 -> 0 的产品并尝试更新为 1,并且在从 1 到 2 的同一“ session ”期间,所以我不明白这怎么可能成为死锁的原因。我在这里缺少什么?

编辑:

虽然我没有提到我如何使用类别和菜单表的信息,但我确实也需要获取它们,它们的使用并不重要,因为我没有对它们进行任何数据库处理。

我曾经使用行级锁定 SELECT FOR UPDATE,但是我遇到了这个问题 MySQL InnoDB dead lock on SELECT with exclusive lock (FOR UPDATE) 中的死锁,所以,我不得不将代码更改为表级锁定

谢谢

最佳答案

这里有几处你做错了。首先,您没有理由对表进行表锁定。 InnoDB 的设计目标之一是它具有行级锁定。

其次,您应该使用 SELECT FOR UPDATE 语句来锁定您正在使用的行,然后执行 UPDATE 和 COMMIT。

我也不明白您为什么要将产品加入类别和菜单,而这些表格只是关于此更新的信息。这看起来像是一个“数据处理”功能。

关于Mysql - 序列化失败 : 1213 Deadlock found when try to get lock; try restarting transaction,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35183046/

有关Mysql - 序列化失败 : 1213 Deadlock found when try to get lock; try restarting transaction的更多相关文章

  1. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  2. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  3. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  4. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  5. ruby - 正则表达式在哪个位置失败? - 2

    我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束

  6. ruby - 使用 rbenv 和 ruby​​-build 构建 ruby​​ 失败,出现 undefined symbol : SSLv2_method - 2

    我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby​​2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby​​-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm

  7. ruby - 在 Ruby 中比较序列 - 2

    假设我必须(小型到中型)阵列:tokens=["aaa","ccc","xxx","bbb","ccc","yyy","zzz"]template=["aaa","bbb","ccc"]如何确定tokens是否以相同的顺序包含template的所有条目?(请注意,在上面的示例中,应忽略第一个“ccc”,从而由于最后一个“ccc”而导致匹配。) 最佳答案 这适用于您的示例数据。tokens=["aaa","ccc","xxx","bbb","ccc","yyy","zzz"]template=["aaa","bbb","ccc"]po

  8. ruby-on-rails - Ruby 的 'open_uri' 是否在读取或失败后可靠地关闭套接字? - 2

    一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我

  9. ruby-on-rails - Ruby 流量控制 : throw an exception, 返回 nil 还是让它失败? - 2

    我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id

  10. ruby - gem 规范失败 - 2

    我正在为毕业设计开发GEM,TravisCI构建不断失败。这是我在Travis上的链接:https://travis-ci.org/ricardobond/perpetuus/builds/8709218构建错误是:$bundleexecrakerakeaborted!Don'tknowhowtobuildtask'default'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_wrapper:14:in`eval'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_

随机推荐