首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >并发编辑闭包树层次结构时的死锁

问并发编辑闭包树层次结构时的死锁
EN

Stack Overflow用户
提问于 2013-02-07 14:48:27
回答 2查看 843关注 0票数 4

当使用树并发操作层次结构上具有公共属性的一组模型时,如何避免数据库死锁?

它们有以下几种味道:

发出一个#append/prepend_sibling时的

代码语言:javascript
复制
Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction:
  UPDATE `elements` SET `sort_order` = `sort_order` + 1 WHERE (`parent_id` = 28035 AND `sort_order` >= 1)

Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction:
  UPDATE `elements` SET `sort_order` = `sort_order` - 1 WHERE (`parent_id` = 21168 AND `sort_order` <= -1)

在重新生成闭包表时

代码语言:javascript
复制
Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction:
  DELETE FROM `element_hierarchies`
   WHERE descendant_id IN (
     SELECT DISTINCT descendant_id
     FROM ( SELECT descendant_id
       FROM `element_hierarchies`
       WHERE ancestor_id = 16332
     ) AS x )
     OR descendant_id = 16332

Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction: 
  INSERT INTO `element_hierarchies` (`ancestor_id`, `descendant_id`, `generations`) VALUES (30910, 30910, 0)

锁定看起来很有前途。有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-10 18:09:22

这里是树的作者:

Heal先生的建议通常是正确的--您应该按照相同的顺序获得表锁,以防止死锁。但是,在这种情况下,死锁是由于层次结构表中的行级锁造成的。

有趣的是,您建议使用锁定!我刚刚为closure_tree编写了这个库,如果您使用的是>= 3.7.0版本,那么已经有了保护类级#rebuild和#find_or_create_by_path方法的建议锁。

咨询锁的问题(至少对于MySQL和PostgreSQL)是,它们不尊重事务边界--如果持有锁的调用方在释放锁之前没有提交事务,其他连接在试图获取咨询锁时不会看到这些更改,因此我们需要在这里小心。我们可能需要为任何写操作在层次结构表上添加一个表锁,但这将是最坏的情况。

我打开了问题41,我们可以在那里追踪它。首先要做的是在并行测试中可靠地再现死锁。我们已经有针对#rebuild和#find_or_create_by_path的测试了。

票数 3
EN

Stack Overflow用户

发布于 2013-02-07 15:19:04

您需要考虑一个事务如何与另一个事务一起工作。最好的办法是确保先读取内容(选择),然后再写SQL。还要确保写SQL以相同的顺序使用表-即在这两种情况下都写入表A然后B。这将防止在另一个事务持有时需要锁,而另一个事务需要另一个事务锁。

或者,您可以检测死锁并采取适当的操作。我建议从一开始就避开它们。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14753906

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档