mysql server has gone away,他的意思就是說,mysql已經走了。
為什麼會出現這種情況呢?原因主要還是跟兩個參數有關:
interactive_timeout 這個是用戶端和伺服器端握手的逾時時間,如果你執行一個大操作的話,握手的時間就要長一點。太久也不好,
有時會出現死循環的操作,握手就會一直握下去,直到系統資源耗完。參數預設值:28800秒(8小時)
wait_timeout 這個是握手完等待的時候,如時超過設定的值,就自動關閉連接配接程序,所占用的資源釋放。參數預設值:28800秒(8小時)
show variables like '%timeout%';
你可以執行上面的指令,看一下你這兩個值的目前的設定
也可以在my.cnf或者my.ini修改一下。
interactive_timeout = 120
wait_timeout = 5
mysql> show variables like '%timeout%';
+-----------------------------+----------+
| variable_name | value |
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| innodb_flush_log_at_timeout | 1 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | off |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 3600 |
| wait_timeout | 28800 |
12 rows in set (0.00 sec)
ysql server has gone away的原因及解決方案
常見的原因:
1. 伺服器逾時,比如說在一個腳本裡連接配接上伺服器後進行了一些資料庫操作後,就開始冷落了資料庫,執行起其他一些非資料庫操作的耗時操作,
資料庫等啊等等啊等,結果逾時了,隻好關閉連接配接。如果是這個原因,請加大wait_timeout。
2. 因為sql語句太長所緻,比如插入一個blob列,或者用一條insert語句同時插入很多行,因為sql太長,資料庫可能就無法接收到完整的 sql,
結果資料庫就會覺得用戶端出錯了,進而關閉連接配接。如果是這個原因,請加大max_allowed_packet。
把php連接配接mysql的連接配接方式從長連接配接改成了短連接配接,就再沒出現了。
1.mysql伺服器的wait_timeout參數為預設的28800秒,即8小時。該參數的意思是mysql等待睡眠的連接配接的持續時間,如果超過8小時不活動,mysql就會關閉這個連接配接。
這個參數可以動态修改,但這個參數是session級别的,需要應用重建立立連接配接擷取這個變量值才會生效。
2.php的預設php.ini裡面,default_socket_timeout參數是預設60s.default_socket_timeout參數的意思是socket逾時為60s。 官方解釋
3.在mysql的官方文檔裡面,有專門的章節介紹mysql server has gone away。但并沒有提及到用戶端本身也會有逾時機制,以前曾經試過把wait_timeout設定為1年
,但app還是繼續出現mysql server has gone away的錯誤。
4.在php程式裡面,如果php.ini修改起來不友善,可以以下代碼來嘗試解決。
ini_set('mysql.connect_timeout', 300);
ini_set('default_socket_timeout', 300);
在ini_set後,可以用ini_get來驗證參數設定适合符合預期。
===================================================================
原因1. mysql 服務宕了
判斷是否屬于這個原因的方法很簡單,執行以下指令,檢視mysql的運作時長
$ mysql -uroot -p -e "show global status like 'uptime';"
+---------------+-------+
| variable_name | value |
| uptime | 68928 |
1 row in set (0.04 sec)
或者檢視mysql的報錯日志,看看有沒有重新開機的資訊
$ tail /var/log/mysql/error.log
130101 22:22:30 innodb: initializing buffer pool, size = 256.0m
130101 22:22:30 innodb: completed initialization of buffer pool
130101 22:22:30 innodb: highest supported file format is barracuda.
130101 22:22:30 innodb: 1.1.8 started; log sequence number 63444325509
130101 22:22:30 [note] server hostname (bind-address): '127.0.0.1'; port: 3306
130101 22:22:30 [note] - '127.0.0.1' resolves to '127.0.0.1';
130101 22:22:30 [note] server socket created on ip: '127.0.0.1'.
130101 22:22:30 [note] event scheduler: loaded 0 events
130101 22:22:30 [note] /usr/sbin/mysqld: ready for connections.
version: '5.5.28-cll' socket: '/var/lib/mysql/mysql.sock' port: 3306 mysql community server (gpl)
如果uptime數值很大,表明mysql服務運作了很久了。說明最近服務沒有重新開機過。
如果日志沒有相關資訊,也表名mysql服務最近沒有重新開機過,可以繼續檢查下面幾項内容。
2. 連接配接逾時
如果程式使用的是長連接配接,則這種情況的可能性會比較大。
即,某個長連接配接很久沒有新的請求發起,達到了server端的timeout,被server強行關閉。
此後再通過這個connection發起查詢的時候,就會報錯server has gone away
$ mysql -uroot -p -e "show global variables like '%timeout';"
+----------------------------+----------+
| variable_name | value |
| connect_timeout | 30 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | off |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| wait_timeout | 28800 |
mysql> set session wait_timeout=5;
## wait 10 seconds
mysql> select now();
error 2006 (hy000): mysql server has gone away
no connection. trying to reconnect...
connection id: 132361
current database: *** none ***
+---------------------+
| now() |
| 2013-01-02 11:31:15 |
1 row in set (0.00 sec)
3. 程序在server端被主動kill
這種情況和情況2相似,隻是發起者是dba或者其他job。發現有長時間的慢查詢執行kill xxx導緻。
$ mysql -uroot -p -e "show global status like 'com_kill'"
| com_kill | 0 |
4. your sql statement was too large.
當查詢的結果集超過 max_allowed_packet 也會出現這樣的報錯。定位方法是打出相關報錯的語句。
用select * into outfile 的方式導出到檔案,檢視檔案大小是否超過 max_allowed_packet ,如果超過則需要調整參數,或者優化語句。
mysql> show global variables like 'max_allowed_packet';
+--------------------+---------+
| variable_name | value |
| max_allowed_packet | 1048576 |
修改參數:
mysql> set global max_allowed_packet=1024*1024*16;
+--------------------+----------+
| variable_name | value |
| max_allowed_packet | 16777216 |
1 row in set (0.00 sec)