天天看點

mysql server has gone away

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)