我一直在寻找一种方法来安全地在模型的方法中运行delete_all,而不是招致网络服务器超时(例如30秒)。
让我们说场景如下:我可能有50K项目记录和150k相关ItemHistory记录。显然使用destroy_all
(加载每个记录的实例并发送单个删除)并不是最佳的。你会如何解决这个问题?我也有delayed_job并尝试使用.delay
方法但不相信它非常适合这个问题。所以,我开始关注Threads,但我想安全地使用它们。
场景#1销毁数十万条过期记录
Thread.new do
Item.expired.find_each do |item|
item.destroy_all # this will also destroy ItemHistory records
end
ActiveRecord::Base.connection.close
end
与前一个问题类似,在Thread中使用事务有什么缺陷(我想这是支持的)?
场景#2 - 在线程中使用交易
Thread.new do
ActiveRecord::Base.transaction do
User.import(account_id)
Item.import(account_id)
end
ActiveRecord::Base.connection.close
end
我需要考虑一些问题吗?
答案 0 :(得分:2)
最好通过将删除移动到后台工作程序来解决。我建议看Sidekiq。
答案 1 :(得分:1)
你试过天真的延迟,就像在
中一样Item.expired.delay.destroy_all
这不好,因为它将获取所有这些项目并在作业正文中序列化它们。这是一个庞大的文本。
你需要做的是一项专门的工作。像这样:
class PruneExpiredItems
def perform
Item.expired.destroy_all
end
end
Delayed::Job.enqueue PruneExpiredItems.new
# or
PruneExpiredItems.new.delay.perform
destroy_all
吗?也就是说,你依靠它来调用你的回调(级联删除和诸如此类的东西)吗?如果没有,您可以尝试delete_all
只向{db}发送DELETE FROM
命令。效率更高。