codeigniter與MySQL server has gone away

最近在做一個處理,於CLI下程式會下指令給splunk撈取資料,並等候splunk回覆結果。最後再將結果寫入資料庫。當查詢大量的資料時,等待splunk的時間會變長。

原本程式運作很正常,但在我重構程式調整操作DB的方式,以符合線上環境使用後,看log卻發現有時居然會出現了以下的錯誤…
A Database Error Occurred
Error Number: 2006
MySQL server has gone away

查了一下mysql官方文件,相關資料如下…
  • http://dev.mysql.com/doc/refman/5.0/en/gone-away.html
  • http://dev.mysql.com/doc/refman/5.0/en/error-messages-client.html#error_cr_server_gone_error

看了說明,我遇到的狀況和time out比較相同。和DBA討論、測試後…果然沒錯…就把問題給解決了~

先說明我做了什麼修改,導致遇到此狀況?

我使用PHP framework- codeigniter,連資料庫時原本使用Multiple Databases模式。在此模式下都會傳回database object,並實際產生(mysql)連線。為了減少連線,我改回一般、正常的連線方式。
  1. //原本連線方式  
  2. $DB1 = $this->load->database('group_one', TRUE);  
  3. //調整後連線方式  
  4. $this->load->database('group_one');  
我改連線方式後,當程式等候splunk時間過久,再去操作資料庫時就會遇到MySQL server has gone away的錯誤

和DBA討論後,把問題發生原因定位在time out。解決之法大概不外乎兩種
  1. client端程式自己重新連線。或者改回我原本的作法。
  2. server端mysql加長timeout時間。
不想因為解決A問題,往後卻產生B問題。於是決定由程式端調整。codeigniter重新連線的作法很簡單,如下…
  1. $this->db->reconnect();  
當等候splunk結束後,呼叫model將資料寫入DB時,使用reconnect()恢復原本連線,就把問題解決了。

其實,codeigniter官方文件Reconnecting / Keeping the Connection Alive的說明也剛好類似我的狀況
If the database server's idle timeout is exceeded while you're doing some heavy PHP lifting (processing an image, for instance), you should consider pinging the server by using the reconnect() method before sending further queries, which can gracefully keep the connection alive or re-establish it.
最後補充一點,codeigniter的reconnect()是使用mysqli_ping()達到reconnet效果。根據PHP文件的說明,其實可以利用修改php.ini方式,做到自動reconnet。作法如下…
  1. ; Allow or prevent reconnect  
  2. ;mysqli.reconnect = Off ;default  
  3. mysqli.reconnect = On  
不過,如此自動是好是壞呢?設定前要多多考慮唷~ :P

留言