mysql - 并发编辑闭包树层次结构时出现死锁

标签 mysql ruby-on-rails-3 deadlock sti transitive-closure-table

使用 closure_tree 时如何避免数据库死锁?在层次结构上同时操作一组具有共同属性的模型?

它们有以下几种口味:

发出#append/prepend_sibling

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)

重建闭包表时

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)

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

最佳答案

作者 closure_tree这里:

先生。 Heal 的建议通常是正确的——您应该以相同的顺序获取表锁以防止死锁。不过,在这种情况下,死锁是由层次结构表中的行级锁引起的。

有趣的是你建议使用 with_advisory_lock !我刚刚为 closure_tree 编写了该库,如果您使用的版本 >= 3.7.0,则已经有保护类级 #rebuild#find_or_create_by_path 的咨询锁方法。

建议锁(至少对于 MySQL 和 PostgreSQL)的问题是它们不遵守事务边界——如果持有锁的调用者在锁释放之前没有提交他们的事务,其他连接将看不到那些当他们尝试获取咨询锁时会发生变化,所以我们在这里需要小心。我们可能需要在层次结构表上为任何写入添加表锁,但这是最坏的情况。

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

关于mysql - 并发编辑闭包树层次结构时出现死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14753906/

相关文章:

分布式系统中的MySQL分片和分区

php - 从 mysql 选择表时编码错误

mysql - 是否需要多个外键?

ruby-on-rails - 创建一个选择标签,其中一些选项已分组,其他选项未分组

ruby-on-rails-3 - Rails 3 完整日历 - 无法更新事件

css - 在 CSS 文件中访问 Ruby 中的语言环境

java - "Unexpected end-of-input in VALUE_STRING"错误可能是什么原因

sql - 分析sql死锁xml

java - 从未收到 SSH 服务器标识 - 握手死锁 [SSHJ]

c++ - 一旦 writer 在 Reader writer lock 中完成写入,Reader 就不会被唤醒