ruby-on-rails - 如何锁定一组对象以进行操作?

标签 ruby-on-rails activerecord transactions locking

在我的rails应用程序中,我有一些类似以下的代码:

def foo
  if object_bar_exists
    raise "can't create bar twice!"
  end

  Bar.create
end

可以由进入应用程序服务器的两个不同请求来调用。如果此代码同时由两个请求运行,并且它们都同时运行if检查,则两个都不会找到对方的bar,并且将创建2个bar

为“酒吧集合”创建“互斥体”的最佳方法是什么?数据库中有特殊用途的互斥表?

更新

我要强调的是,我不能在这里使用内存互斥锁,因为并发是跨请求/进程而不是线程的。

最佳答案

最好的办法是在数据库事务中执行操作。因为您最终可能会运行多个应用程序,并且它们很可能不会共享内存,所以您将无法在应用程序级别上创建Mutex锁,尤其是当这两个应用程序服务在完全不同的物理设备上运行时。这是完成数据库事务的方法:

ActiveRecord::Base.transaction do
  # Transaction code goes here.
end

如果要确保对数据库事务进行回滚,则必须在Bar类上启用验证,以便无效的保存请求将导致回滚:
ActiveRecord::Base.transaction do
  bar = Bar.new(params[:bar])
  bar.save!
end

如果数据库中已经有条形对象,则可以这样悲观地锁定该对象,如下所示:
ActiveRecord::Base.transaction do
  bar = Bar.find(1, :lock => true)
  # perform operations on bar
end

关于ruby-on-rails - 如何锁定一组对象以进行操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5424322/

相关文章:

ruby-on-rails - 在 Rails 中将继承转换为组合

javascript - 在选项卡式导航中打开模式 - Bootstrap 3 & Rails 4

ruby-on-rails - 使用 ActiveRecord::Serialization.to_xml 构建动态字段

java - GWT RPC 调用在运行时异常后不会回滚事务

mysql - 在不同的机器上 hibernate 两个同时发生的事务

mysql - 如何使用地理编码器和其他搜索工具搜索附近的数据?

ruby-on-rails - Rails 禁用 POST/PUT/PATCH 正文的 JSON 解析

ruby-on-rails - Rails ActiveRecord 助手查找方法不急于加载关联

mysql - 给定语句的 ActiveRecord 等效 SQL

java - 当 @Transactional 注解中指定回滚已检查异常时,Spring 是否会回滚运行时异常