編輯:使用MySQL ...解決在軌的競爭條件(僅限於Y X的數量)
假設你有一個應用程序,增加了學生的一類,而這個類的空間有限...所以你這樣做:
def add
if some_classroom.size < MAX_SIZE
add_student_to_class
end
end
這是一個多線程環境中的競態條件。瘸。
假設我們
- 不想要這個,和
- 不希望鎖定我們的教室表或記錄(這將導致我們的應用程序在其他地方吸)
做什麼我們的確是?
我提出這樣的:
class Classroom < ActiveRecord::Base
has_one :classroom_lock
after_create :create_lock_record
def create_lock_record
c = ClassroomLock.new
c.classroom = self
c.save!
end
end
class ClassroomLock < ActiveRecord::Base
belongs_to :classroom
end
def add
c = Classroom.first
ActiveRecord::Base.transaction do
c.classroom_lock.lock!
c = Classroom.first #load this again (it might have changed)
if c.size < MAX_SIZE
c.add_new_student(some_student)
else
do_stuff_about_not_enough_room
end
end
end
這似乎像它應該赫然工作。我的(虛構)Classroom#show方法不會被阻止,因爲課堂記錄實際上並未鎖定,並且add方法實際上是單線程的,因爲任何其他進程都將被迫等待鎖定!直到鎖定被釋放。
這是行不通的?也許?我想是這樣?我不知道...
我已經做了一個錘擊這一步與多個進程一次,但它很難確定(畢竟這是一個競爭條件)。
任何人都可以提供一些額外的見解嗎?
您正在使用什麼數據庫? – meagar 2012-03-02 15:28:28
我正在使用mysql – jsharpe 2012-03-02 15:33:26
使用'LOCK IN SHARE MODE'。拋出你的手卷解決方案,看看http://guides.rubyonrails.org/active_record_querying.html#pessimistic-locking – meagar 2012-03-02 15:38:48