2014-03-26 102 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

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