2011-05-07 97 views
10

我需要什麼:ActiveRecord在事務中執行批量插入/刪除操作嗎?

  1. 保證(無記錄可被處理2次)
  2. 所有1000行批量刪除所選

@queue = Queue.where("col = 1").limit(1000) 
ids = [] 
@queue.each do |row| 
    Queue.do_something(row) 
    ids << row.id 
end 

Queue.delete_all("id in (#{ids.join(',')}) ") 

是一樣的原子更新

Queue.transaction do 
    @queue.each do |row| 
     Queue.do_something(row) 
     Queue.delete(row.id) 
    end 
end 

回答

15

對於插入:

使用事務時,ActiveRecord不執行批量插入。然而,它確實提高了一點,因爲它使用單個事務來執行所有的INSERT語句,而不是每個INSERT語句的一個事務。

所以:

Queue.transaction do 
    @queue.each do |row| 
    # an INSERT is done here 
    end 
end 

將是快於:

@queue.each do |row| 
    # an INSERT is done here 
end 

有關如何真正做到批量插入更多的信息,看看這個article

對於刪除:

ActiveRecord的delete_all調用是一個單獨的SQL DELETE語句,所以我想你可以認爲這是一個批量刪除(沒必要在這裏使用一個事務,因爲它是在一個事務中通過的ActiveRecord已經封裝)。在每條記錄上調用delete時情況並非如此,這將導致多個SQL DELETE語句,從而啓動並提交多個事務並且整體上性能較低。

+0

在我的情況下,我需要刪除記錄,同時確保沒有其他進程/實例將處理相同的記錄。我使用mysql「FOR UPDATE」SQL子句來鎖定選定的記錄並使用ActiveRecord事務,因爲我認爲ActiveRecord會將這些刪除作爲單個批量刪除sql執行或者更快地執行。 – newx 2011-05-07 18:24:31

+0

問題是我的電子郵件(在QUEUE上的記錄)交付了兩次 – newx 2011-05-07 18:25:14

+0

使用您的解決方案時,它確實獲得了更快的速度......謝謝! :-) – 2012-09-15 10:16:03

相關問題