2014年3月28日 星期五

[MySQL]server has gone away 解法

應用程序(比如PHP)長時間的執行批量的MYSQL語句。執行一個SQL,但SQL語句過大或者語句中含有BLOB或者longblob字段。比如,圖片數據的處理。都容易引起MySQL server has gone away。

Step.1 SQL 命令超過最大長度了?

有時可能為了一些比較特別的存取而兜出一串很長的 SQL 命令,這時候就可能會發生SQL 命令超過最大長度的問題。調整 SQL 命令的最大長度可以更改 my.cnf(例如:/etc/my.cnf)中的 max_allowed_packet 欄位,將原有數值加大。

例如:
  原本是 max_allowed_packet = 1M,
  改成  max_allowed_packet = 10M(也可以設置自己需要的大小)

  ※參數作用:用來控制其通信緩衝區的最大長度。

之後重跑 MySQL server 後再試一次(命令: service mysqld stop; service mysqld start)。


Step.2 調整連線的逾時的數值

修改 my.cnf(例如: /etc/my.cnf)中的 wait_timeout 和 interactive_timeout 數值。

例如改成:
  wait_timeout=2880000
  interactive_timeout = 2880000

  ※如果原本沒有設置,就在[mysqld](一般模式)後面加入。

儲存修改內容以後重跑 MySQL server,然後再試試看。如果無法更動 my.cnf 檔案的話,可以在 SQL 語法中,例如在 mysql_query(`SET NAMES`) 之後,下 mysql_query(`SET SESSION wait_timeout = 2880000; SET SESSION interactive_timeout = 2880000`, $rLink); 之類的命令。

如果無效,請回復原數值,然後嘗試下一項。


Step.3 每次建立 MySQL 連線時都重新建立一條連線

最不得已的一步......@@

mysql_connect('localhost', $sUser, $sPasswd, TRUE);

也就是 mysql_connect 的第四個參數設定成 TRUE,這樣每次建立 MySQL 連線時都重新建立一條連線,以避免前一個 MySQL 連線未結束,而後來建立的 MySQL 連線取得和前一個MySQL 連線一樣的 PHP resource ID,造成 mysql server has gone away 問題。



最後,附上其他影響的參數與建議值

key_buffer = 看情況~
  表示索引緩衝區的大小,嚴格說是它決定了資料庫索引處理的速度,尤其是索引讀的速度。可以檢查狀態值Key_read_requests和Key_reads,即可知道key_buffer_size設置是否合理。比例key_reads / key_read_requests應該盡可能低,至少是1:100,1:1000更好,這個比值接近1:20000。


table_cache = 4096
  表快取記憶體的大小。當Mysql訪問一個表時,如果在Mysql表緩衝區中還有空間,那麼這個表就被打開並放入表緩衝區,這樣做的好處是可以更快速地訪問表中的內容。一般來說,可以通過查看資料庫運行峰值時間的狀態值Open_tables和Opened_tables,用以判斷是否需要增加table_cache的值,即如果open_tables接近table_cache的時候,並且Opened_tables這個值在逐步增加,那就要考慮增加這個值的大小了。

  在mysql預設安裝情況下,table_cache的值在2G記憶體以下的機器中的值默認時256到512,如果機器有4G記憶體,則預設這個值是2048,但這決意味著機器記憶體越大,這個值應該越大,因為table_cache加大後,使得mysql對SQL回應的速度更快了,不可避免的會產生更多的鎖死(dead lock),這樣反而使得資料庫整個一套操作慢了下來,嚴重影響性能。所以平時維護中還是要根據庫的實際情況去作出判斷,找到最適合的table_cache值。


sort_buffer_size = 2M
  是每個需要排序的線程分配的緩衝區大小,增加該值可以加速 order by 和 group by  的操作。注意:該參數是以每個連接分配內存,也就是說,如果有16個連接,sort_buffer_size 為 64K,那麼實際分配的內存為:16 ×  64K = 1MB。如果設置的緩存大小無法滿足需要,MySQL 會將數據寫入磁碟來完成排序。因為磁碟操作和內存操作不在一個數量級,所以  sort_buffer_size 對排序的性能影響很大。

net_buffer_length = 8K
Each client thread is associated with a connection buffer and result buffer. Both begin with a size given by net_buffer_length but are dynamically enlarged up to max_allowed_packet bytes as needed. The result buffer shrinks to net_buffer_length after each SQL statement.

This variable should not normally be changed, but if you have very little memory, you can set it to the expected length of statements sent by clients. If statements exceed this length, the connection buffer is automatically enlarged. The maximum value to which net_buffer_length can be set is 1MB.

read_buffer_size = 256K
Each thread that does a sequential scan allocates a buffer of this size (in bytes) for each table it scans. If you do many sequential scans, you might want to increase this value, which defaults to 131072. The value of this variable should be a multiple of 4KB. If it is set to a value that is not a multiple of 4KB, its value will be rounded down to the nearest multiple of 4KB.

The maximum permissible setting for read_buffer_size is 2GB.

read_rnd_buffer_size = 512K
When reading rows in sorted order following a key-sorting operation, the rows are read through this buffer to avoid disk seeks. Setting the variable to a large value can improve ORDER BY performance by a lot. However, this is a buffer allocated for each client, so you should not set the global variable to a large value. Instead, change the session variable only from within those clients that need to run large queries.

The maximum permissible setting for read_rnd_buffer_size is 2GB.

myisam_sort_buffer_size = 64M
The size of the buffer that is allocated when sorting MyISAM indexes during a REPAIR TABLE or when creating indexes with CREATE INDEX or ALTER TABLE.

The maximum permissible setting for myisam_sort_buffer_size is 4GB.


參考資料:
[MySQL] 解決MySQL server has gone away問題
解決MySQL server has gone away
MySQL server has gone away 解法
Mysql调优中两个重要参数table_cache和key_buffer
64MB VPS 下優化 MySQL


MySQL-中文說明

沒有留言:

張貼留言