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