0
我有一个应用程序,其中人们注册的项目。每个项目的插槽数量有限。我该如何处理并发?我试过这样的项目类:并发关联在ActiveRecord中
def sign_up(signup)
ActiveRecord::Base.transaction do
return 'Sorry, that item is full.' if full?
signups << signup
sheet.save!
nil
end
end
def full?
locked_signups = signups.lock(true).all
locked_signups.size >= max_signups
end
是我试图通过AR甚至可能做什么?我是否需要通过列实现自己的锁定?欢迎任何建议。
更新:我得到了这个工作每塔德曼的答案。以下是可用的代码:
rows_updated = ActiveRecord::Base.transaction do
Item.connection.update "update items set signup_count=signup_count+1 where id=#{ActiveRecord::Base.sanitize(self.id)} and signup_count<quantity"
end
return 'Sorry, that item is full. Refresh the page to see what\'s still open.' if rows_updated < 1
使用任一选项,我们不会有同样的并发问题吗?第二个(第三,第四等)用户在先前用户声明一个插槽(通过插入一个新注册行)之后并且在提交signups_remaining更新之前读取signups_remaining值。 –
这两者都是可靠的,因为在第一种情况下,如果库存不足,查询将不会返回执行结果,而在第二种情况下,您只会声明与当前未分配一样多的查询。 'WHERE allocation_id IS NULL'确保它不会覆盖以前的任何工作。这是可能的,因为这些都是单原子语句,既可以运行也可以不运行。两个单独的查询更难同步。 – tadman