ActiveRecord 触摸导致死锁

2024-07-04

我的应用程序使用touch广泛地利用 Rails 的模板缓存系统。当批量中的许多不同对象之间创建许多关系时,我的应用程序会执行某种类型的工作。有时,其中一些工作会导致级联touches 导致死锁。

我可以针对这种情况进行编码,我经常看到这种情况发生,但看到它却揭示了更大的问题,这可能会发生在其他情况下,尽管可能性很小。

要理解这一点,请想象两个人在同一时刻在 Twitter 上互相关注。他们都单击“关注”,从而在他们之间创建关系对象,然后他们的每条记录都被创建touch编辑。如果这些接触交织在一起:

  1. 进程1接触用户A
  2. 进程2接触用户B
  3. 进程1接触用户B
  4. 进程2接触用户A

每个进程都使用一个数据库事务,因此这会导致死锁。

我是否错了,这可能发生在我奇怪的批处理作业场景之外的正常应用程序操作中?如果我没记错的话,有什么解决办法吗?我可以以某种方式移动touch是在交易之外吗? (无论如何,最后一次写入获胜对于更新updated_at来说是可以的......)

更新 - 数据模型的更多解释

class Follow
  belongs_to :follower, touch: true
  belongs_to :followee, touch: true
end

@u1 = User.find(1)
@u2 = User.find(2)

# Background Job 1
Follow.create!(follower: @u1, followee: @u2)

# Background Job 2
Follow.create!(follower: @u2, followee: @u1)

不确定是什么导致了死锁,但您可以在处理两条记录时添加悲观锁,这将阻止另一个请求处理它们,直到锁被释放,ActiveRecord将等待锁释放后再继续。

User.transaction do
  @u1, @u2 = User.lock.where(id: [1,2])
  # Those two records are now locked, other transaction instances
  # can't proceed till this transaction block is exited 
  Follow.create!(follower: @u1, followee: @u2)
end
# lock is released here

Note:通过id: [2,1]不会按该顺序返回它们,因此您需要处理该情况。

Note 2:太多的锁定可能会影响您的整体应用程序性能,因为用户模型可能是一个频繁使用的模型,但我想这一切都取决于这些后续发生的频率。


Update: Here's a second way that also might work, first the follow model, no touches, but instead an after_create
class Follow
  belongs_to :follower
  belongs_to :followee

  after_create :touch_users

  def touch_users
    # no locking and direct database update
    User.where(id: [follower.id, followee.id]).update_all(updated_at: :Time.now)
  end
end

然后控制器会执行正常的事务,或者根本不执行,因为你不需要它

Follow.create!(follower: @u1, followee: @u2)

NOTE: #update_all不会触发 activerecord 回调,并且查询直接在数据库上完成(如果有的话)after_update方法,那么您可能希望避免使用此方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ActiveRecord 触摸导致死锁 的相关文章

随机推荐

  • 如何减少 Node 应用程序在 Google App Engine 上的部署时间

    现在时间约为 10 分钟 但我的应用程序在 npm install 上使用了 2 分钟 应用程序引擎在每次部署时都会执行此操作 然后运行大约 5 秒 为什么需要这么长时间 有什么技巧可以降低这个时间吗 我在其他地方听说这是因为改变了路线 并
  • Cython 动态库链接

    我实际上正在尝试将现有的 C 库链接到我的 Cython 程序 我可以访问该库的入口点标头 h 其中所有函数声明为 EXPORT API int stdcall LibFunction 我想EXPORT API用于创建 dll declsp
  • 可编辑列表视图

    我希望在 C winforms 应用程序中创建一个可编辑的 ListView 用户可以双击单元格来更改其内容 如果有人能为我提供一些指导和 或示例 那就太好了 我不打算使用任何商业产品 你问错了问题 ListView 不是正确的控件 使用数
  • 我应该使用内存数据库而不是模拟我的存储库吗?

    我喜欢在测试时使用内存数据库 例如 SQLite 的想法 而不是为我的存储库创建模拟 这样我还可以测试我的存储库的代码 而不会出现任何性能问题 该策略的优点和缺点是什么 如果我使用 ORM 我通常倾向于在内存数据库中使用 sqlite 来测
  • 如何将 pandas DataFrame 保存到 Excel 文件?

    我正在尝试从 Web 源加载数据并将其保存为 Excel 文件 但不知道该怎么做 我应该怎么办 import requests import pandas as pd import xmltodict url https www kstan
  • Phonegap 应用程序性能与本机应用程序性能

    我们正在考虑构建一个条形码扫描应用程序 我们正在考虑使用 PhoneGap 但我们唯一担心的是速度 该应用程序要做的只是扫描条形码并检查服务器以查看其是否有效 该应用程序非常频繁地使用相机通过图像扫描条形码 我的主要问题是 通过phoneg
  • 从Matlab到C++特征矩阵运算——向量归一化

    将一些 Matlab 代码转换为 C 问题 如何在 C 中 连接矩阵中的两个向量 已经找到解决办法了 标准化每个数组 pts col 除以它的第三个值 1和2的Matlab代码 1 A 3x1 vector d0 d1 double B d
  • 是否可以将附件视图的顺序更改为 drupal 页面视图?

    我有一个页面显示的视图 其中基本上包含内容 A 该内容存在于一列中 此外 我还有另外 6 个附件显示 在另一列中显示内容 B C D E 等 是否可以修改附加视图的显示顺序 现在我已将它们全部设置为附加在内容 A 页面之后 我不是 100
  • 如何在列之间留出空间?

    我有一个文本文件 如下所示 我想在第五列中的字符和数字之间留一个空格 我怎样才能用 awk 做到这一点 cxe 911 bv heg A1029 53 030 bvf 912 cv lya A1030 51 99 Desired outpu
  • 将 HTML 表格导出到 Excel 在 IE 中不起作用

    将 HTML 表格导出到 Excel 在 Chrome 和 Firefox 中工作正常 但在 Internet Explorer 10 中不起作用 var tableToExcel function var uri data applica
  • 定位彩条 - Matplotlib

    我有一个合并两个数据的图 鉴于此 我必须显示两个不同的颜色条 每个数据一个 我目前正在绘制数据如下 plt figure Data 1 fig plt imshow data1 interpolation nearest cmap bina
  • C# 奇怪的精度丢失 int 到浮动和向后

    当尝试从 int 转换为 float 并向后转换时 会发生奇怪的事情 原始示例代码 整数值 28218681 val 28218681 浮点 fVal 浮点 val fVal 2 821868E 07 int val2 int fVal v
  • PHP SQLSRV:sqlsrv_query() 是否可以正确地准备 select 语句?

    TL DR Does sqlsrv query 做同样的工作select陈述比sqlsrv prepare and sqlsrv execute 关于准备好的陈述 做什么 我怎样才能做一个安全的select陈述 一点历史 我是 PHP 开发
  • Opencv 3D 来自立体对中的点

    OpenCV 中是否有一个简单的函数可以从立体相机对中获取对象的 3D 位置和姿态 我用棋盘校准了相机和基线 我现在想要获取一个已知的物体 就像同一个棋盘一样 在它自己的坐标中具有已知的 3D 点 并找到真实世界的位置 在相机坐标中 有一些
  • 在 Visual Studio 中启动 Web API 项目的最简洁方法(无视图)

    删除 Visual Studio API 模板通常附带的所有额外内容 如视图和其他如果您只想拥有 WebAPI 服务则不需要的内容 的最干净方法是什么 我假设 VIEWS 文件夹用于 MVC 视图 也许我错了 它需要有一个正在运行的 API
  • Python就地写入文件任意位置

    我正在尝试在 python 中就地编辑文本文件 它非常大 因此无法将其加载到内存中 我打算替换我在里面找到的逐字节字符串 with f as open filename txt r b if f read 8 01234567 f seek
  • UIWebView 中自动填充用户名和密码

    我正在为我做一个非常简单的应用程序 当我启动这个应用程序时 它只会将我带到这个网页https social tre it expert https social tre it expert 我想自动登录 那么有没有办法自动填写用户名和密码
  • Java中等待的最佳方式

    我有一个应用程序需要等待一段未知的时间 它必须等到服务器完成几个数据字段的填充 服务器的 API 为我提供了一种请求数据的方法 非常简单 服务器的 API 还提供了一种接收回数据的方法 一次接收一个字段 它没有告诉我所有字段何时完成填充 等
  • 如何按字母顺序对单键字典数组进行排序?

    我想对 Facebook 的 Graph API 返回的好友列表进行排序 排序后的结果需要是按好友名字的字母顺序排列 name Joe Smith id 6500000 name Andrew Smith id 82000 name Dor
  • ActiveRecord 触摸导致死锁

    我的应用程序使用touch广泛地利用 Rails 的模板缓存系统 当批量中的许多不同对象之间创建许多关系时 我的应用程序会执行某种类型的工作 有时 其中一些工作会导致级联touches 导致死锁 我可以针对这种情况进行编码 我经常看到这种情