Ruby on rails Rails 3.2 ActiveRecord并发性
我有一个应用程序是任务管理器 每个用户都可以选择要分配给自己的新任务 如果两个用户同时接受同一任务,是否存在并发问题 我的代码如下所示:Ruby on rails Rails 3.2 ActiveRecord并发性,ruby-on-rails,activerecord,concurrency,Ruby On Rails,Activerecord,Concurrency,我有一个应用程序是任务管理器 每个用户都可以选择要分配给自己的新任务 如果两个用户同时接受同一任务,是否存在并发问题 我的代码如下所示: if @user.task == nil @task.user = @user @task.save end 如果两个不同的用户在两台不同的机器上同时打开此url。我会有问题吗?您可以使用来防止其他“过时”记录保存到数据库中。要启用它,您的模型需要有一个默认值为0的lock\u version列 从数据库中提取记录时,会附带当前的lock\u版本。当
if @user.task == nil
@task.user = @user
@task.save
end
如果两个不同的用户在两台不同的机器上同时打开此url。我会有问题吗?您可以使用来防止其他“过时”记录保存到数据库中。要启用它,您的模型需要有一个默认值为0
的lock\u version
列
从数据库中提取记录时,会附带当前的lock\u版本
。当记录被修改并保存到数据库中时,数据库行会有条件地更新,方法是在获取记录时出现的lock\u版本上约束UPDATE
。如果未更改,更新
将增加锁定版本
。如果已更改,则更新将不会执行任何操作,并且将引发异常(ActiveRecord::StaleObjectError
)。这是ActiveRecord的默认行为,除非按如下方式关闭:
ActiveRecord::Base.lock_optimistically = false
您可以(可选)使用lock\u version
以外的列名。要使用自定义名称,请在模型类中添加一行,如下所示:
set_locking_column :some_column_name
乐观锁的另一种替代方法是,它依赖于数据库级别的表级或行级锁。此机制将阻止对锁定行的所有访问,因此可能会对您的性能产生负面影响。从未尝试过此机制,但您可以使用它
您应该能够获得特定任务的锁定,类似于:
@task = Task.find(some_id)
@task.with_lock do
#Then let's check if there's still no one assigned to this task
if @task.user.nil? && @user.task.nil?
@task.user = @user
@task.save
end
end
再说一次,我从来没有用过这个,所以我会在锁里面用一个大的sleep
来测试它,以确保它能以你想要的方式锁定所有东西
我也不确定这里的重新加载。由于该行已锁定,因此可能会失败。但是在获得锁后,您必须确保您的对象是来自db的新对象,可能还有其他方法可以做到这一点
编辑:无需重新加载,我检查了源代码,并用_lock
为您执行此操作。
关于这一点:我仍然不明白,但我认为这就是我需要的“乐观锁定”(根据您的链接)是上面在答案中描述的。