假設我們有兩個表之間常見的M-M的關係,如:ActiveRecord的:避免的has_many關係不一致
用戶 --- < users_tags> --- 標籤。
在這篇文章中,我只關心關係user_tags,標籤:我想避免鏈接標籤可以被刪除。只有未被引用的標籤應該是可銷燬的。
愚蠢的方式做,這將是:
class Tag
def before_destroy
unless self.user_tags.empty?
raise "error"
end
end
end
但我覺得有一個潛在的競爭條件,檢查user_tags.empty之間?和實際的刪除。
第二種方法可能是在檢查是否還有任何引用之前鎖定整個表user_tags表。
而第三種方式,我能想到的會涉及更改它創建實際的參考代碼:
添加引用到users_tags:
- 取標籤
- 鎖定(以避免併發銷燬)
- 在users_tag中創建參考
- 提交
的before_destroy處理程序,然後可以:
- self.lock!
- 檢查是否有任何引用
- 毀滅自我
- 提交
有沒有更好的辦法來做到這一點?哪一個可靠/最好?我個人傾向於第二個,因爲它只需要before_destroy控制器中的邏輯,但是要鎖定整個表的成本。
編輯1:
雖然與LOCK TABLE嘗試圍繞我意識到,他們是在玩對我的交易。當使用innodb時,您可以使用事務(及其鎖定功能)或使用LOCK/UNLOCK表,這兩種世界的混合使情況變得更糟(LOCK/UNLOCK導致隱式提交,我錯過了文檔中的警告)。但這只是協議。
(編輯2(幾周後):我再次與這個問題進行了抗爭。所以我想再次強調,不要使用LOCK TABLE)
我現在傾向於父對象(在本例中標籤))上使用共享鎖增加孩子的時候,和FOR更新鎖定刪除。但是我仍然想知道它是否應該是這樣的(在父表中更新子表時鎖定一個Rang)。
Btw。我也意識到這個問題現在完全獨立於軌道:)。
這就是正確的,只是使用innodbs自己的參照完整性系統會使這些事情變得更容易。 rails的方式是使用rails helper而不是定義所有的東西兩次,不確定這是否是最好的方法。 我喜歡你在刪除語句中的子查詢的方法,我懷疑有類似的東西。那聲明是原子的,對吧? – reto 2009-06-23 23:10:02