在執行一個sql文件時mysql -h 127.0.0.1 -uroot study -e"source b.sql"
,報錯MySQL server has gone away
。上網查解決辦法,按照網上的解決方法一步步操作,最終找到原因并且解決了,覺得有必要總結下這個問題發生的原因及解決辦法,避免后面再繼續踩坑。
情況1. MySQL服務宕機
執行以下命令,查看mysql的運行時長。
mysql> show global status like 'uptime';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Uptime | 10170 |
+---------------+-------+
uptime數值很大,表明mysql服務運行很久,說明最近MySQL服務器沒有重啟過。
或者查看MySQL的報錯日志,看看有沒有重啟的信息。
datou:~$ tail /var/log/mysql/error.log
170914 19:44:37 InnoDB: Completed initialization of buffer pool
170914 19:44:37 InnoDB: highest supported file format is Barracuda.
170914 19:44:37 InnoDB: Waiting for the background threads to start
170914 19:44:38 InnoDB: 5.5.57 started; log sequence number 58681764
170914 19:44:38 [Note] Server hostname (bind-address): '127.0.0.1'; port: 3306
170914 19:44:38 [Note] - '127.0.0.1' resolves to '127.0.0.1';
170914 19:44:38 [Note] Server socket created on IP: '127.0.0.1'.
170914 19:44:38 [Note] Event Scheduler: Loaded 0 events
170914 19:44:38 [Note] /usr/sbin/mysqld: ready for connections.
Version: '5.5.57-0ubuntu0.14.04.1' socket: '/var/run/mysqld/mysqld.sock' port: 3306 (Ubuntu)
如果日志沒有相關信息,也表明mysql服務最近沒有重啟過,可以繼續檢查下面幾項情況。
情況2. 連接超時
如果程序使用的是長連接,則這種情況的可能性會比較大。
即,某個長連接很久沒有新的請求發起,達到了server端的timeout,被server強行關閉。
此后再通過這個connection發起查詢的時候,就會報錯server has gone away。
mysql> show global variables like '%timeout';
+----------------------------+----------+
| Variable_name | Value |
+----------------------------+----------+
| connect_timeout | 10 |
| 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 |
+----------------------------+----------+
10 rows in set (0.00 sec)
如下命令設置連接超時為5秒。
mysql> SET SESSION wait_timeout=5;
Query OK, 0 rows affected (0.00 sec)
再執行SELECT NOW();
,通過這個connection發起查詢的時候,就會報錯server has gone away。
mysql> SELECT NOW();
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 41
Current database: study
+---------------------+
| NOW() |
+---------------------+
| 2017-09-14 23:12:53 |
+---------------------+
1 row in set (0.01 sec)
實際上wait_timeout=28800,不是造成文章開頭的原因。
情況3. 進程在server端被主動kill
這種情況和情況2相似,只是發起者是DBA或者其他job。發現有長時間的慢查詢執行kill xxx導致。
mysql> show global status like 'com_kill';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_kill | 0 |
+---------------+-------+
1 row in set (0.00 sec)
情況4. Your SQL statement was too large.
當查詢的結果集超過 max_allowed_packet 也會出現這樣的報錯。
查看執行SQL執行文件大小是否超過 max_allowed_packet ,如果超過則需要調整參數,或者優化語句。
mysql> show global variables like 'max_allowed_packet';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 16777216 |
+--------------------+----------+
1 row in set (0.00 sec)
計算發現SQL執行文件最大只能是16M,而文章開頭執行的a.sql有24M。
修改參數,max_allowed_packet 調整為28M。
mysql> set global max_allowed_packet=1024*1024*28;
Query OK, 0 rows affected (0.00 sec)
mysql> show global variables like 'max_allowed_packet';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 29360128 |
+--------------------+----------+
1 row in set (0.00 sec)
重新再執行`mysql -h 127.0.0.1 -uroot study -e"source b.sql"``成功,說明原因是情況4造成的。