ActiveRecord批量数据,内存不断增长

5

我正在使用ActiveRecord批量迁移一张表的数据到另一个数据库中的不同表中,大约有400万行。

我使用find_each按批次获取记录。然后对每个获取的记录进行一些逻辑操作,并将其写入到另一个数据库中。我尝试过直接逐个写入以及使用很好的activerecord-import gem进行批量写入。

但是,在任何情况下,我的ruby进程内存使用量在整个导出/导入过程中都会大幅增长。我认为使用find_each,我正在获取1000个批次,每次只应该有1000个批次在内存中...但是,似乎每个我获取的记录都会消耗内存,直到进程结束。

有什么想法吗?ActiveRecord是否在缓存某些东西,我可以关闭它?

更新于2012年1月17日

我想我要放弃了。我已经尝试过:

  • 确保所有内容都包装在ActiveRecord::Base.uncached do
  • 添加ActiveRecord::IdentityMap.enabled = false(我认为应该关闭当前线程的标识映射,尽管它没有明确说明,并且我认为标识映射在当前Rails中默认情况下未启用)

这两者似乎都没有太大的影响,内存仍在泄漏。

然后我添加了一个定期显式执行:

  • GC.start

这似乎减缓了内存泄漏的速度,但内存泄漏仍在发生(最终耗尽所有内存并崩溃)。

所以我想我要放弃了,并决定目前无法使用AR从一个数据库读取数百万行并将其插入到另一个数据库中。也许MySQL特定代码(我的数据库)或其他地方的AR中存在内存泄漏,或者别的什么问题。


没有代码的情况下,我一点头绪都没有。 - Frederick Cheung
代码非常简单,几乎只是按照描述所做的。这是实际的文件,如果这里还有太多无用的东西,我可以提供一个简化的演示案例,不涉及周围设置和动态创建AR模型等。 https://github.com/team-umlaut/umlaut/blob/e583824dd15520c146e3cd020d762591b179803d/lib/tasks/umlaut_migrate_permalinks.rake - jrochkind
嘿@jrochkind,你找到这个问题的解决方案了吗?请分享一下,我也遇到了同样的问题。提前感谢! - Abhishek
不,我放弃了。 - jrochkind
2个回答

1
我建议将每个工作单元排队到Resque队列中。我发现当迭代大型数组时,Ruby存在一些怪癖。
有一个主线程按ID排队工作,然后有多个Resque工作者访问该队列以完成工作。
我已经在大约30万条记录上使用了这种方法,因此它很可能可以扩展到数百万条记录。

0
将第86行更改为bulk_queue = [],因为bulk_queue.clear仅将数组的长度设置为0,使GC无法清除它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接