Joh*_*hir 5 activerecord locking transactions ruby-on-rails
在我的rails应用程序中,我有一些这样的代码:
def foo
if object_bar_exists
raise "can't create bar twice!"
end
Bar.create
end
Run Code Online (Sandbox Code Playgroud)
这可以通过进入应用程序服务器的两个不同请求来调用.如果此代码同时由两个请求运行,并且它们同时运行if
检查,则不会找到另一个bar
,并且bar
将创建2 秒.
为"酒吧集合"创建"互斥体"的最佳方法是什么?DB中的专用互斥表?
更新
我应该强调,我不能在这里使用内存互斥,因为并发是跨请求/进程而不是线程.
最好的办法是在数据库事务中执行操作.因为您最终可能会运行多个应用程序并且它们很可能不会共享内存,所以您将无法在应用程序级别创建Mutex锁定,尤其是当这两个应用程序服务在完全不同的物理机箱上运行时.以下是如何完成数据库事务:
ActiveRecord::Base.transaction do
# Transaction code goes here.
end
Run Code Online (Sandbox Code Playgroud)
如果要确保在数据库事务上回滚,则必须在Bar类上启用验证,以便无效的保存请求将导致回滚:
ActiveRecord::Base.transaction do
bar = Bar.new(params[:bar])
bar.save!
end
Run Code Online (Sandbox Code Playgroud)
如果数据库中已经有一个bar对象,则可以像这样悲观地锁定该对象:
ActiveRecord::Base.transaction do
bar = Bar.find(1, :lock => true)
# perform operations on bar
end
Run Code Online (Sandbox Code Playgroud)