循环遍历大量记录时,Ruby on Rails内存泄漏; find_each没有帮助

WYi*_*WYi 32 activerecord memory-leaks ruby-on-rails ruby-on-rails-3

我有一个Rails应用程序,可以处理mysql数据库中的大量(数百万)记录.一旦它开始工作,它的内存使用速度就会以每秒50MB的速度快速增长.使用像oink这样的工具,我能够将根本原因缩小到一个循环,该循环遍历数据库中大表中的所有记录.

我知道如果我使用像Person.all.each这样的东西,所有记录都会被加载到内存中.但是,如果我切换到find_each,我仍然会看到相同的内存问题.为了进一步隔离这个问题,我创建了以下测试控制器,它除了遍历记录外什么都不做.我想find_each每次只在内存中保留少量对象,但内存使用在执行时会线性增长.

class TestController < ApplicationController
  def memory_test
    Person.find_each do |person|
    end
end
Run Code Online (Sandbox Code Playgroud)

我怀疑它与ActiveRecord缓存查询结果有关.但我检查了我的环境设置,并且我确实在开发中将所有与缓存相关的选项设置为false(我使用rails创建的默认设置).我在网上做了一些搜索,但找不到解决方案.

我使用rails 3.1.0 rc1和ruby 1.9.2

谢谢!

WYi*_*WYi 41

我能够自己解决这个问题.有两个地方需要改变.

首先,禁用IdentityMap.在config/application.rb中

config.active_record.identity_map = false
Run Code Online (Sandbox Code Playgroud)

其次,使用uncached来包装循环

class MemoryTestController < ApplicationController
  def go
    ActiveRecord::Base.uncached do
      Person.find_each do |person|
        # whatever operation
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

现在我的记忆力得到了控制.希望这有助于其他人.

  • 根据文档,[`identity_map` 默认禁用](http://apidock.com/rails/ActiveRecord/IdentityMap),所以你只需要确保它在你当前的配置中没有设置为 true(至少我会想——要自己测试一下)。 (3认同)