2014-03-26 100 views
14

我们正在在Heroku Rails应用程序遇到一个奇怪的问题。中庸之道之后,从Rails的3.2.17迁移到Rails的4.0.3我们PostgreSQL服务器显示内存使用量的增加无限,然后返回在每次请求以下错误:内存泄漏升级后导轨4

ERROR: out of memory 
DETAIL: Failed on request of size xxx 

中庸之道解除与轨道4的申请后, postgresql内存开始增加。

正如你可以看到下面的截图,它从500 MO增加到比3,5Go更在3小时内

enter image description here

同时,每秒提交一倍。它由120通过每秒承诺:

enter image description here

280每秒承诺:

enter image description here

值得注意的是,当我们重新启动应用程序,存储再往正常值的600 Mo之前超过3几小时后(然后每个SQL请求显示'内存不足'错误)。这就像杀死ActiveRecord连接在postgresql服务器上释放内存一样。

我们可能有内存泄漏的地方。 但是:

  • 它在Rails 3.2中工作得很好。也许这个问题是我们为使代码适应Rails 4和Rails 4代码本身所做的更改之间的结合。轨道4升级后每秒中庸之道提交数
  • IHE增加似乎很奇怪。

我们的堆栈是:

  • 的Heroku,X2 DYNOS
  • PostgreSQL中,在Heroku伊卡计划
  • 麒麟,3名工人每个实例
  • 的Rails 4.0.3
  • Redis的缓存。
  • 值得注意的宝石:延迟作业(4.0.0),活动管理员(在主分支),舒适的沙发墨西哥(1.11.2)

一切似乎在我们的代码真正看中的。

我们PostgreSQL的配置是:

  • work_mem:100MB
  • 的shared_buffers:1464MB
  • MAX_CONNECTIONS:500
  • maintenance_work_mem:64MB

是否有人曾经经历过这样的行为,当切换到Rails 4?我正在寻找重现的想法。

非常欢迎所有帮助。

在此先感谢。

+0

在Pg中,你的'shared_buffers','max_connections','work_mem'和'maintenance_work_mem'是什么? –

+0

感谢Craig,问题用这些信息更新。 –

+1

您的最大内存使用量至少为100MB * 500 + 1464MB,因此接近52GB。难怪你有问题。特别是因为单个会话可以使用'work_mem'几次来处理更复杂的查询(每个操作不是每个查询)。 –

回答

19

我不知道什么更好:回答我的问题或更新它...所以我选择回答。请让我知道是否更新更好

我们终于找出问题所在。从版本3.1开始,Rails就像User.find(id)这样简单的请求添加了准备好的语句。版本4.0,为关联请求添加了准备好的语句(has_many,belongs_to,has_one)。 对于为例下面的代码:

class User 
    has_many :adresses 
end 
user.addresses 

生成请求

SELECT "addresses".* FROM "addresses" WHERE "addresses"."user_id" = $1 [["user_id", 1]] 

的问题是Rails的只能加准备好的声明变量外键(这里USER_ID)。如果使用自定义的SQL请求,像

user.addresses.where("moved_at < ?", Time.now - 3.month) 

它不会添加一个变量为moved_at准备好的声明。因此,每次调用请求时都会生成一个准备好的语句。 Rails处理最大大小为1000的池的预处理语句。

但是,postgresql预处理语句不通过连接共享,因此在一两个小时内每个连接都有1000个预处理语句。其中一些非常大。这导致postgreqsl服务器上的内存消耗非常高。

+0

谢谢。谢谢。谢谢!这一直困扰着我整整一个月,直到我发现这一点。 – kizzx2

+1

回答你自己的问题是可以的。你也应该接受它作为正确的答案。 –

+0

非常感谢!你救了我的一天! –