首页 > 解决方案 > 如果已经为用户运行,Rails 6 防止多模型逻辑启动的方法是什么?

问题描述

我有一些复杂的业务逻辑,当控制器动作被击中时运行。该逻辑对与用户关联的许多不同表/记录执行各种更新。但是,如果路由连续命中足够快,控制器调用的模型方法很容易同时运行多次。

我想确保模型方法由于先前的请求而已经在处理中时不会启动。

我做了一些阅读,听起来数据库锁定可能是我想要的,但我不清楚我想要什么的锁定,或者我是否真的想要它用于我的场景。我对这类问题没有经验。

我的逻辑不仅更新一条记录,它还更新一条用户记录以及与该用户关联的许多不同记录,跨越许多表。lock_version在每个表中添加 a 对我来说似乎不正确,但也许这很正常?我认为我想要的是在此方法运行时冻结用户和用户的相关关联记录,因此我正在寻找实现这一目标的最佳方法。

Rails 处理这个问题的方法是什么(希望)尽可能少地增加复杂性?如果锁定是我想要的,我是否需要为lock_version每个因此逻辑而更新的模型添加一列?

标签: ruby-on-railsrails-activerecorddatabase-locking

解决方案


创建一个受您正在处理的用户唯一约束的互斥锁,无论是使用 Ruby ,还是使用一致的数据库(如果您正在构建分布式应用程序)。

在一个动作开始处理之前,让它尝试获取一个互斥体。如果它因为另一个进程已经拥有它而失败,请停止。

确保任何获得互斥锁的进程在停止处理后都会释放它。

lock_version很重要,但它只是一个数据库锁。它确保如果对象已被另一个进程更新,则无法保存该对象。

如果您正在进行原子提交lock_version它将起作用,但最好在进入提交阶段之前检查并发处理。诸如此类的“进程级”锁是您自己必须实现的。


推荐阅读