2008-09-19 80 views
38

當我們的Ruby on Rails應用程序運行了一段時間後,它開始拋出500個「MySQL服務器已經消失」。通常這在一夜之間發生。它最近開始這樣做,我們的服務器配置沒有明顯的變化。Ruby on Rails「MySQL服務器已經消失」

Mysql::Error: MySQL server has gone away: SELECT * FROM `widgets` 

重新啓動mongrels(不是MySQL服務器)修復它。

我們該如何解決這個問題?

回答

22

這可能是由於到MySQL消失的持久連接引起的(超時可能是,如果它發生在夜間)和Ruby on Rails是無法恢復連接,它應該是默認這樣做:

在文件供應商/軌道/ ActionPack的/ LIB/action_controller/dispatcher.rb是代碼:

if defined?(ActiveRecord) 
    before_dispatch { ActiveRecord::Base.verify_active_connections! } 
    to_prepare(:activerecord_instantiate_observers) {ActiveRecord::Base.instantiate_observers } 
end 

verify_active_connections!執行若干動作的方法,其中之一是,以重新創建任何過期的連接。

此錯誤的最可能的原因是,這是因爲monkey patch重新定義了調度員不叫verify_active_connections!,或者verify_active_connections!已經改變等

+2

是的;當遇到這個問題時,我通過捕獲一次`ActiveRecord :: StatementInvalid`並手動調用`ActiveRecord :: Base.verify_active_connections!`來解決問題。 – conny 2010-01-25 01:06:38

+0

@Conny,'ActiveRecord :: StatementInvalid`去哪裏?在`application_controller.rb`中?或者其他地方 – 2011-12-12 18:21:28

+1

@ChristianFazzini,這是一個獨立的守護進程,它提供了一個特定於應用程序的目的:我從來沒有在普通的舊式Rails Web應用程序中遇到這個問題。如果我有,現在我將使用Rails 2.3或更新,並使用重新連接選項[由mixonic建議](http://stackoverflow.com/a/1175186/23023) – conny 2011-12-13 04:01:40

1

與MySQL服務器的連接可能超時。

你應該可以增加MySQL中的超時時間,但是爲了正確的修復,讓你的代碼檢查數據庫連接是否還活着,如果不是,則重新連接。

1

您是否監視打開的MySQL連接或線程的數量?什麼是你的max.connections的mysql.ini設置?

mysql> show status; 

查看Connections,Max_used_connections,Threads_connected和Threads_created。

您可能需要增加MySQL配置中的限制,或者rails可能無法正確關閉連接*。

注:我只用Ruby on Rails的簡單...

服務器狀態的MySQL文檔是http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html

4

由於其他貢獻者此主題已表示,它由於不活動,MySQL服務器很可能已關閉與Ruby on Rails應用程序的連接。默認超時時間爲28800秒,即8小時。

set-variable = wait_timeout=86400 

添加此行到您的/etc/my.cnf將提高超時24小時 http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#option_mysqld_wait_timeout

儘管文檔沒有指出它,但值可能會完全禁用超時,但您需要進行試驗,因爲這只是推測。

然而,我知道有三種情況可能會產生這種錯誤。首先是MySQL服務器重新啓動。這顯然會丟棄所有的連接,但是由於MySQL客戶端是被動的,並且直到您執行下一個查詢時纔會被注意到。

第二個條件是,如果有人從MySQL命令行殺死你的查詢,這也斷開連接,因爲它可以讓客戶在一個不確定的狀態。

最後的是,如果你的MySQL服務器重新啓動本身因爲一個嚴重的內部錯誤。也就是說,如果你正在做的對錶的簡單查詢,立刻就能看到「MySQL已經走了」,我會拿你的服務器日誌的密切關注,以檢查硬件錯誤,或數據庫損壞。

1

在database.yml中使用reconnect:true將導致數據庫連接在引發ActiveRecord :: StatementInvalid錯誤後重新建立(正如Dave Cheney提到的那樣)。

不幸的是增加對數據庫操作的重試似乎要警惕連接超時:

begin 
    do_some_active_record_operation 
rescue ActiveRecord::StatementInvalid => e 
    Rails.logger.debug("Got statement invalid #{e.message} ... trying again") 
    # Second attempt, now that db connection is re-established 
    do_some_active_record_operation 
end 
0

我曾在一個Ruby這個問題on Rails的3個應用程序,使用mysql2寶石。我抄襲了這個有問題的查詢,並試圖直接在MySQL中運行它,並且我得到了同樣的錯誤,「MySQL服務器已經消失」。

有問題的查詢是非常非常大的。一個非常大的插入(+1   MB)。我試圖插入到該領域是一個TEXT列,其最大尺寸爲64   KB。而不是拋出一個錯誤,連接就消失了。

我增加字段的大小,得到了相同的事情,所以我仍然不知道確切的問題了。重點是由於一些奇怪的查詢,它在數據庫中。無論如何!

2

首先,確定MAX_CONNECTIONS在MySQL:

show variables like "max_connections"; 

你需要確保你在你的Ruby on Rails應用程序進行連接的數量少於連接的最大允許數量。請注意,額外連接可能來自cron作業,delayed_job進程(每個進程在您的database.yml中將具有相同的池大小)等。

在您瀏覽應用程序,運行進程等時監視SQL連接。通過執行以下操作在MySQL:

show status where variable_name = 'Threads_connected'; 

你可能要考慮一個Thread執行完畢後關閉連接的數據庫連接不會自動關閉(我認爲這是對軌道4個應用Reaper少使用Ruby的問題):

Thread.new do 
    begin 
    # Thread work here 
    ensure 
    begin 
     if (ActiveRecord::Base.connection && ActiveRecord::Base.connection.active?) 
      ActiveRecord::Base.connection.close 
     end 
     rescue 
     end 
    end 
end 
1

嘗試用Ruby ActiveRecord::Base.connection.verify! on Rails的4驗證的ping服務器並重新連接,如果沒有連接它。

2

我在向MySQL發送真正大的語句時遇到此問題。 MySQL限制了語句的大小,並且如果超過限制,它將關閉連接。

set global max_allowed_packet = 1048576; # 2^20 bytes (1 MB) was enough in my case